当我用“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() 才能被编译器正确运行。检查所有先决条件 从面向对象的角度来看,动态调度让我觉得很奇怪,因为封装丢失了。

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

有帮助吗?

解决方案

http://dlang.org/dbc.html

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

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

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

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

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

其他提示

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

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

不过,这可能很难进入,沃尔特热衷于不进行重大改变。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top