interfacedcontracts

How can I meaningfully use precondition contracts in D interfaces?


When I override functions in D with "in" contracts, then the inherited "in" contracts are checked. If they fail, then the overridden "in" contracts are checked. If I don't specify any in contract, then it is interpreted as if there is an empty "in" contract. So the following code compiles and runs successfully.

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 only want the precondition of I.write() to be checked when I call i.write() since that is what is statically known to be sufficient for I.write() to run correctly by the compiler. Checking all preconditions after dynamic dispatch strikes me as odd from an OO perspective since encapsulation is lost.

I could repeat the precondition or write in { assert( false ); } in all classes implementing the interface, but that's a pain. Is that a design error in the D language? Or is there any proper scalable way to do that?


Solution

  • http://dlang.org/dbc.html

    If a function in a derived class overrides a function in its super class, then only one of the in contracts of the function and its base functions must be satisfied. Overriding functions then becomes a process of loosening the in contracts.

    A function without an in contract means that any values of the function parameters are allowed. This implies that if any function in an inheritance hierarchy has no in contract, then in contracts on functions overriding it have no useful effect.

    Conversely, all of the out contracts needs to be satisfied, so overriding functions becomes a processes of tightening the out contracts.

    It is actually a difficult design puzzle when polymorphic behavior comes into question. Look, for example, at this bug report with related long discussion: http://d.puremagic.com/issues/show_bug.cgi?id=6857

    Regarding question how to achieve wanted behavior - mixin's always work when copy-paste needs to be prevented, but I am not sure that it is OK to do it from the point of Design By Contract paradigm. Unfortunately, need someones more theoretically competent in this question advice.