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