5

当我用“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语言的设计错误吗?还是有任何适当的可扩展方式来做到这一点?

4

3 回答 3

3

http://dlang.org/dbc.html

如果派生类中的函数覆盖其超类中的函数,则必须满足该函数及其基函数的 in 契约之一。然后,覆盖函数就变成了一个放松 in 合约的过程。

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

相反,需要满足所有的输出合同,因此覆盖功能成为收紧输出合同的过程。

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

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

于 2012-07-27T10:18:19.883 回答
0

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

于 2012-07-27T20:47:12.827 回答
0

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

不过,这可能很难进入,Walter 非常重视没有重大变化的事情。

于 2012-07-31T03:06:06.957 回答