In contract inheritance (Was: Re: [Issue 302] New: in/out contract inheritance yet to be implemented)

Stewart Gordon smjg_1998 at yahoo.com
Sat Aug 26 07:30:46 PDT 2006


Bruno Medeiros wrote:
<snip>
> Does this makes sense? If in-contracts should be less restrictive than 
> their parents (and they should), why allow in-contracts that are not 
> less restrictive? Isn't this behavior more adequate:
> «In a derived function, *all* in-contracts must be satisfied.

Basic OO principle: whatever is doable on an object of a base class
should be doable on an object of any class derived from it.

> If the first in-contract fails, then it is a programmer error on regards 
> to using the function.
> If the first in-contract passes, but any parent in-contract fails, then 
> there is an error in the function specification itself, since the 
> in-contracts are not less restrictive.»

Which is the "first" in-contract?
- the one of the hierarchy level where the function is introduced in the
first place?
- the one in the class of which the object reference is declared to be?
- the one in the actual class of the object?

And what does "parent" mean - base or derived?  I would have thought
base, but you seem to be using it to mean derived.

Perhaps:

"If the in-contract in the class of the object reference fails, then it 
is an error from the caller's point of view.  If this in-contract 
passes, but the in-contract in any derived class fails, then there is an 
error in the function specification itself, since the in-contract of the 
derived class imposes new restrictions."

However, this leads to code duplication if the derived class wants to 
leave the base class's in-contract unchanged.  (Which is bound to be the 
case if the derived class function unconditionally calls the base class 
function on the same arguments and then does more.)  By the current 
spec, one can achieve this by simply using

     in {
         assert (false);
     }

in the derived class.  Which indeed is cryptic, but can you think of a 
better idea?  Moreover, what if you're deriving from a library class, 
and the library author improves the function in the base class to work 
in more cases.  Should you be able to use this improved functionality 
straight out of the box?

> Consider this example:
> 
> -----
> class Foo {
>   void cfunc(int a)
>   in {
>     assert(a != 42);
>   } body {
>     writefln("Foo.cfunc: != 42 ", a);
>   }
> 
> }

So on any object of class Foo, cfunc can be called with any argument
that is not 42.

> class FooBar : Foo {
>   override void cfunc(int a)
>   in {
>     assert(a != 666);
>   } body {
>     writefln("FooBar.cfunc: != 666 ", a);
>   }
> }
> -----
> 
> The in-contract of derived cfunc is not conceptually valid, but DMD 
> allows it. It would be nice to detect that at compile-time but that is 
> likely not feasible in the general-case, so perhaps we could opt for the 
> aforementioned behavior, that would detect this at runtime?

But how?  When a function in a derived class is called, should it call 
all the in-contracts leading down to it, to make sure that all 
in-contracts from a certain level down to it pass and all in-contracts 
above it fail?

A further matter of debate is whether, given

     Qwert yuiop = new Asdfg;
     yuiop.hjkl();

the in-contract from Qwert (type of the object reference) or Asdfg 
(actual class of the object) should be used.  Of course, the natural way 
to implement it depends on whether the in-contract is enforced on the 
caller side or the callee side.

Since the programmer has used a Qwert reference, then it's more a matter 
of using Qwert correctly than of using Asdfg correctly.  Another 
advantage of enforcing in-contracts on the caller side is that one build 
of a library can sensibly be used for both development and release 
builds of applications, and the application programmer would still have 
the checking that he/she/it is using the library correctly.

Walter once criticised the idea of doing it this way claiming that it 
leads to "code bloat", but I'm not convinced it's serious enough 
(considering the amount of code bloat in development builds anyway) to 
outweigh the benefits.

Stewart.

-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d- s:-@ C++@ a->--- UB@ P+ L E@ W++@ N+++ o K-@ w++@ O? M V? PS-
PE- Y? PGP- t- 5? X? R b DI? D G e++++ h-- r-- !y
------END GEEK CODE BLOCK------

My e-mail is valid but not my primary mailbox.  Please keep replies on
the 'group where everyone may benefit.




More information about the Digitalmars-d mailing list