可以指定成员函数作为属性名.
这样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 {
        // ...
    }
}

加个假这样,防止不检查.因为条件是||...