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*x + y*y + z*z);
}
/* invariant是D语言契约(contract)式编程的一个工具,
用来描述class固定不变的特性(characteristics);
invariant代码在类的实例构造之后、析构之前,public函数的调用时和调用完成后被调用
*/
invariant
{
assert(z*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();
}
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*x + y*y + z*z);
}
/* invariant是D语言契约(contract)式编程的一个工具,
用来描述class固定不变的特性(characteristics);
invariant代码在类的实例构造之后、析构之前,public函数的调用时和调用完成后被调用
*/
invariant
{
assert(z*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();
}