可以指定成员函数
作为属性名.
这样a.b
,b就可能是函数,只要前面加了@属性
..length
属性不能修改静态数组.对切片,有可能会分配空间,甚至移动到新位置+初化新成员.
因为属性,所以调用函数,可以不加()
.
struct Rectangle {
double width;
double height;
}
auto garden = Rectangle(10, 20);
writeln(garden.area);
struct Rectangle {
double width;
double height;
double area() const @property {
return width * height;
}//常,保证本函数不修改本对象
}
这样,就强制保证了一致性
.不会被修改.
auto garden = Rectangle(10, 20);
writeln("面积为: ", garden.area);
就像第三个成员变量一样使用.
void area(double newArea) @property {
auto scale = sqrt(newArea / area);
width *= scale;
height *= scale;
}
修改,作为set
.
当然.也能够实现成员函数的只读访问,即用个函数包装成员.不允许设置(即写)in,out
用于保证函数的不变.而类/构
则:
class School {
private:
Student[] students;
size_t femaleCount,maleCount;
invariant() {//用这个不变量来保证
assert(students.length == (femaleCount + maleCount));
}
// ...
}
可在构
中定义.可以有多个invariant()
块.
可在构造器后,析构器前
,及在执行公有/导出成员函数前后
,导出函数是导出在动态库接口
中的函数.dmd deneme.d -w -release
,发布时依然禁用了.发布太厉害了.接口和类
成员也可有in/out
,允许为他们定义基本的限制(前条件)
或者为用户定义后条件
继承类可在覆盖的函数中
定义进一步的in/out
,可松可严格.只要有一个满足相应的限制块
就行了.in
块只相应的满足就行.即进块可以变松,只要不出现断定错误就可
.如果父级失败,就执行子级进块
,相当于||…||…out
块所有限制都要满足.则是(…&&…)
执行函数时in
/out
从最上到下一层层检查.
interface Iface {
int[] func(int[] a, int[] b)
in {
writeln("Iface.func.in");
assert(a.length == b.length);
} out (result) {
writeln("Iface.func.out");
assert((result.length % 2) == 0);
}
}
class Class : Iface {
int[] func(int[] a, int[] b)
in {//放松了.
writeln("Class.func.in");
assert((a.length == b.length) ||
(a.length == 0) ||
(b.length == 0));
} out (result) {
writeln("Class.func.out");
assert((result.length != 0) &&
(result[0] == result[$ - 1]));
} body {//示例块
writeln("Class.func.body");
int[] result;
if (a.length == 0) {a = b;}
if (b.length == 0) {b = a;}
foreach (i; 0 .. a.length) {
result ~= a[i];result ~= b[i];
}
result[0] = result[$ - 1] = 42;
return result;
}
}
import std.stdio;
void main() {
auto c = new Class();
writeln(c.func([1, 2, 3], []));
}
示例:
class Protocol {
void compute(double d)
in {
assert(d > 42);
} body {
// ...
}
}
class SpecialProtocol : Protocol {
/* Because it does not have an 'in' block, this function
* effectively disables the preconditions of
* 'Protocol.compute', perhaps unintentionally. */
override void compute(double d) {
// ...
}
}
void main() {
auto s = new SpecialProtocol();
s.compute(10); /* BUG: Although the value 10 does not
* satisfy the precondition of the
* superclass, this call succeeds. */
}
子块,不检查in
块,结果出错.按道理子块
也要继承父块
的前提条件.
class SpecialProtocol : Protocol {
override void compute(double d)
in {
assert(false);//加个永远假.
} body {
// ...
}
}
加个假这样,防止不检查.因为进
条件是||...