当我使用“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语言中的设计错误吗?或者有没有适当的可扩展方式来做到这一点?
答案 0 :(得分:3)
如果派生类中的函数覆盖其超类中的函数,则只能满足函数及其基函数的一个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
这可能是一个很难进入的人,沃尔特对于没有突破性变化的事情很重要。