2012-07-27 56 views
5

当我使用“in”契约覆盖D中的函数时,将检查继承的“in”契约。如果它们失败,则检查重写的“in”合同。如果我没有在合同中指定任何内容,那么它就会被解释为有一个空的“in”合同。所以下面的代码编译并成功运行。我该如何有意义地在D接口中使用预条件契约?

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

http://dlang.org/dbc.html

如果在派生类中的函数将覆盖其超类中的函数,那么只有在函数的合同,它的基础功能的一个必须得到满足。重写函数然后成为放松契约的过程。

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

相反,所有的外包合同都需要满足,所以重要的功能就变成了收紧合同的过程。

当多态行为出现问题时,它实际上是一个困难的设计难题。例如,看看这个bug报告以及相关的长篇讨论:http://d.puremagic.com/issues/show_bug.cgi?id=6857

关于如何实现想要的行为的问题 - 当需要防止复制粘贴时,mixin始终工作,但我不确定是否可以做它来自设计合同范式。不幸的是,需要更多理论上能够胜任这个问题建议的人。

+0

我不确定该文档页是不是只是过时。我不得不看看TDPL,但有一个类似于OP的问题:http://d.puremagic.com/issues/show_bug.cgi?id=6549 – jpf 2012-07-27 18:34:37

+0

@jpf这是一个增强请求。有些人想要改变这个问题的语言。有关当前行为的文档是正确的。 – 2012-07-27 18:38:36

+0

哦,对,我没有意识到这一点。 – jpf 2012-07-28 12:47:19

0

D中的前提条件是要求函数正确运行。如果你重载了函数,那么你为它编写了一个新的代码,旧的前提条件 - 这是旧代码的一个要求 - 不一定是新代码的要求。

相关问题