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

时间:2012-07-27 07:06:08

标签: interface d contracts

当我使用“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;
}

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

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

3 个答案:

答案 0 :(得分:3)

http://dlang.org/dbc.html

  

如果派生类中的函数覆盖其超类中的函数,则只能满足函数及其基函数的一个in合约中的一个。然后,覆盖函数将成为放松合同的过程。

     

没有合同的函数意味着允许任何函数参数值。这意味着如果继承层次结构中的任何函数在契约中没有,那么在函数覆盖它的契约中没有任何有用的效果。

     

相反,所有的合同都需要得到满足,所以压倒一切的功能就成了收紧合同的过程。

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

关于如何实现通缉行为的问题 - 当需要防止复制粘贴时,mixin总能正常工作,但我不确定从Design By Contract范例的角度来看它是否可行。不幸的是,在这个问题建议中需要一些理论上更有能力的人。

答案 1 :(得分:0)

D中的前提条件是函数正确运行的要求。如果重载函数,则为其编写新代码,旧的前置条件 - 这是旧代码的要求 - 不一定是新代码的要求。

答案 2 :(得分:0)

因此,虽然没有直接讨论接口,但这个问题是http://d.puremagic.com/issues/show_bug.cgi?id=6856

这可能是一个很难进入的人,沃尔特对于没有突破性变化的事情很重要。