如何在D接口中有意义地使用前提条件契约?

Ral*_*zky 5 contracts d interface

当我使用"in"合约覆盖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;
}
Run Code Online (Sandbox Code Playgroud)

我只想在I.write()调用时检查前提条件,i.write()因为这是静态已知的足以I.write()使编译器正确运行的内容.动态调度之后检查所有前提条件从OO角度来看是奇怪的,因为封装丢失了.

我可以重复前提条件或写入in { assert( false ); }实现接口的所有类,但这很痛苦.这是D语言中的设计错误吗?或者有没有适当的可扩展方式来做到这一点?

Mih*_*uns 3

http://dlang.org/dbc.html

如果派生类中的函数重写其超类中的函数,则只需满足该函数及其基函数的契约之一。然后,重写函数就变成了放松契约的过程。

没有 in 契约的函数意味着函数参数的任何值都是允许的。这意味着,如果继承层次结构中的任何函数没有契约,那么重写它的函数的契约就没有任何作用。

相反,所有的外部契约都需要得到满足,因此压倒性的功能就变成了一个收紧外部契约的过程。

当多态行为受到质疑时,这实际上是一个困难的设计难题。例如,查看此错误报告以及相关的长时间讨论:http://d.puremagic.com/issues/show_bug.cgi?id=6857

关于如何实现想要的行为的问题 - 当需要防止复制粘贴时,mixin 总是有效,但我不确定从“按合同设计”范式的角度来看是否可以这样做。不幸的是,需要有人在这个问题上更有理论能力的建议。