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();
    
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章