インターフェース

Dはinterfaceという、技術的にはclassに似ていますが、 そのメンバ関数はinterfaceから継承したクラスに 実装されなければならないものを定義できます。

interface Animal {
    void makeNoise();
}

makeNoiseメンバ関数は、DogAnimalインターフェースを継承しているために Dogに実装されなければいけません。 本質的にmakeNoiseは基底クラスのabstractメンバ関数のように振る舞います。

class Dog : Animal {
    override void makeNoise() {
        ...
    }
}

auto dog = new Dog;
Animal animal = dog; // インターフェースへの暗黙的なキャスト
animal.makeNoise();

classが実装できるinterfaceの数は無制限ですが、継承は1つの基底クラスからのみできます。

NVI (non virtual interface) パターン

NVIパターン は共通したインターフェースに対して 非 virtual メソッドを許可します。 それによって、このパターンは共通した実行パターンに対する違反を防ぎます。 Dではinterfaceにおいてfinal(つまりオーバーライド禁止)関数を定義できるようにすることでNVIパターンを実現します。 これによりinterfaceにおける他の関数のオーバーライドによる、特殊化した振る舞いのカスタマイズが可能になります。

interface Animal {
    void makeNoise();
    final doubleNoise() // NVI pattern
    {
        makeNoise();
        makeNoise();
    }
}

掘り下げる

rdmd playground.d