D語言遊戲編程(8):D語言基礎之class

    D語言的class不支持多繼承 ,對象的實例只能使用引用類型,但是它不只是簡單的一個C++的簡化。D語言的class書寫起來更方便,例如使用this作爲構造函數的名稱,對於虛函數不需要指定virtual屬性,編譯器會自動判斷哪些函數需要列入vtabl。D語言的class在契約式編程方面提供兩個方便的工具:invariant和unittest。下面是一些主要特性的演示代碼。

import std.stdio;
import std.math;

void main()
{
    tryClass();
}


class MyBaseClass
{
    
static float c;
    
static this()    // static constructor用來初始化靜態成員, 會在main()之前被調用
    {
        c 
= 1;
    }

    
    
static ~this()    // 靜態析構函數在程序結束時被調用
    {
        writefln(
"program exit");
    }

    
    
float x;
    
float y = 9;    // 可以指定默認的初始值
    
    
this(float _x, float _y)    // 構造函數
    {
        writefln(
"MyBaseClass.ctor");
        x 
= _x;
        y 
= _y;
    }

    
~this()    // Destructors
    {
        writefln(
"MyBaseClass.dtor");
    }

}


class MySubClass : MyBaseClass    // 只能使用單繼承
{
    
float z;
    
    
this(float _x, float _y, float _z)    // 構造函數
    {
        writefln(
"MySubClass.ctor");
        
        super(_x, _y);    
//調用父類的構造函數
        z = _z;
    }

    
~this()    // Destructors
    {
        writefln(
"MySubClass.dtor");
    }

    
    
float getLength()
    
{
        
return sqrt(x*+ y*+ z*z);
    }

    
    
/* invariant是D語言契約(contract)式編程的一個工具,
       用來描述class固定不變的特性(characteristics);
       invariant代碼在類的實例構造之後、析構之前,public函數的調用時和調用完成後被調用
      
*/

    invariant
    
{
        assert(z
*>= 0);
        writefln(
"-- MySubClass.invariant");
    }

    
    
/*    unittest
        使用dmd的"-unittest"命令行參數將unittest代碼編譯進最終的可執行文件;
        unittest代碼在靜態構造之後在main之前被自動調用
    
*/

    unittest
    
{
        writefln(
"%% MyClassSubClass.unittest");
    }

}


// Scope
//----------------------------------
/*     scope類的實例必須以scope屬性來聲明;
    當scope類的實例離開作用域時會自動析構函數, 包括拋出異常的時候
*/

scope 
class MyScopeClass
{
    
int a;
    
int b;
    
    
~this()
    
{
        writefln(
"go out of scope");
    }

}


//----------------------------------------------
void Foo()
{
    scope MyScopeClass s 
= new MyScopeClass;
}


void tryClass()
{
    
// 類的實例都是引用類型,使用new操作符創建
    MyBaseClass m = new MyBaseClass(1,2);
    
    
// Field Properties
    
//----------------------------
     m.x = 100// field都使用“.”來引用,不再需要::和->
     writefln("offset of y = ", m.y.offsetof);
     
     
// tupleof
     m.tupleof[0= 99;    // m.x
     m.tupleof[1= 98;    // m.y
 
     
foreach(float e;m.tupleof)
         writef(e,
"");
     writefln();
     
     
// 如果一個類沒有指明基類,則是從Object派生的
     writefln(m.toString());    // 調用Object方法
     
     MySubClass s 
= new MySubClass(1,2,3);
     writefln(
"call MySubClass.getLength()");
     
float length =  s.getLength();
     writefln(
"length = ", length);
     
     assert(s); 
// 手動調用invariant
     
     
// Scope class
     Foo();
    
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章