5

D の関数を "in" コントラクトでオーバーライドすると、継承された "in" コントラクトがチェックされます。それらが失敗した場合、オーバーライドされた「in」コントラクトがチェックされます。コントラクトに何も指定しない場合、空の「イン」コントラクトがあるかのように解釈されます。したがって、次のコードは正常にコンパイルおよび実行されます。

module main;
import std.stdio;

interface I
{
    void write( int i )
    in
    {
        assert( i > 0 );
    }
}

class C : I
{
    void write( int i )
    {
        writeln( i );
    }
}

int main()
{
    I i = new C;

    i.write( -5 );
    getchar();

    return 0;
}

コンパイラが正しく実行するのに十分であることが静的にわかっているため、呼び出すときに前提条件のみI.write()をチェックする必要があります。動的ディスパッチ後にすべての前提条件をチェックすると、カプセル化が失われるため、オブジェクト指向の観点から奇妙に思えます。i.write()I.write()

前提条件を繰り返したりin { assert( false ); }、インターフェイスを実装するすべてのクラスに記述したりできますが、それは面倒です。D言語の設計ミスですか?または、それを行うための適切なスケーラブルな方法はありますか?

4

3 に答える 3

3

http://dlang.org/dbc.html

派生クラスの関数がそのスーパー クラスの関数をオーバーライドする場合、関数とその基本関数のコントラクトの 1 つだけを満たす必要があります。関数のオーバーライドは、イン コントラクトを緩めるプロセスになります。

in contract のない関数は、関数パラメーターの任意の値が許可されることを意味します。これは、継承階層内の関数にコントラクトがない場合、それをオーバーライドする関数のコントラクトでは有用な効果がないことを意味します。

逆に言えば、すべてのアウト コントラクトを満たす必要があるため、関数のオーバーライドはアウト コントラクトを締めるプロセスになります。

ポリモーフィックな動作が問題になると、実際には難しい設計パズルになります。たとえば、関連する長い議論を含むこのバグレポートを見てください: http://d.puremagic.com/issues/show_bug.cgi?id=6857

希望の動作を実現する方法についての質問 - コピーと貼り付けを防ぐ必要がある場合、ミックスインは常に機能しますが、Design By Contract パラダイムの観点からそれを実行しても問題ないかどうかはわかりません。残念ながら、この質問のアドバイスには、より理論的に有能な人が必要です。

于 2012-07-27T10:18:19.883 に答える
0

したがって、この問題は、インターフェイスについて直接議論されていませんが、http://d.puremagic.com/issues/show_bug.cgi?id=6856です。

これは入りにくいかもしれませんが、Walter は破壊的変更がないことを重視しています。

于 2012-07-31T03:06:06.957 に答える
0

D の前提条件は、関数が正しく実行されるための要件です。関数をオーバーロードする場合は、新しいコードを記述します。古いコードの要件である古い前提条件は、必ずしも新しいコードの要件ではありません。

于 2012-07-27T20:47:12.827 に答える