structs, classes, interfaces - Part III, Solution

Martin Hinsch m.hinsch at rug.nl
Sat Sep 1 09:04:18 PDT 2007


On Sat, 01 Sep 2007 16:20:44 +0300, Jari-Matti Mäkelä wrote:

> Martin Hinsch wrote:
> 
>> The basic idea behind my solution is actually really simple. You just
>> have to realize that (OOP-) inheritance as it is usually done is a
>> combination of two different concepts - composition and polymorphism.
>> What would happen if we disentangled these concepts?
>> 
>> My suggestion would be to completely remove virtual functions from the
>> language. Instead use interfaces to provide ad hoc runtime polymorphism.
>> 
>> As before interfaces define a set of methods a class has to provide. As
>> before you can let a class derive from an interface to declare (and let
>> the compiler check) its conformance to the interface. But now this is
>> not obligatory anymore.
> 
>> I think this solves all problems I mentioned above except one, which is
>> slicing. To be honest I never saw the particular danger in that one in
>> the first place. Maybe I'm totally missing something but isn't that just
>> another case of a lossy cast? In that case my proposal solves that
>> problem as well since all potentially lossy (slicy ;-) casts can be
>> detected at compile time and the user warned.
>> 
>> I have no illusions concerning the probability of this making it into D.
>> Still I think it's a nice idea ;-) and I would be really interested in
>> hearing what people think about it.
> 
> I'm not sure if I understood you correctly, but isn't this exactly the
> thing that was discussed recently. From language consistency POV
> 
>> class A {...}
>> class B {...}
>> 
>> class C : A,B {...}
> 
> is a bit problematic because D doesn't have multiple inheritance. A trait
> class construct could be possible though, but I cannot say if the added
> complexity to the core language is good. However, the interface compliance
> could be enforced that way (and Walter seems to like it too, see slides).
> Implementation could be mixed in with an extended mixin syntax:
> 
> interface IA { void foo(); }
> interface IB { int bar(); }
> 
> struct A : IA { void foo() { writefln("hello"); } struct B : IB { int
> bar() { return 42; } }
> 
> struct C : IA, IB {
>   mixin A;
>   mixin B;
> }
> }
> I've noticed mixin is a powerful mechanism. MI is more or less a
> combination of interface part and mixed in implementation and provides a
> lot less flexibility.

Yes, as I said, the "enhanced composition" part has been discussed
recently. However only for structs and only in a very specific way.

Anyways the point of my proposal is not that but rather that run-time
polymorphism is completely separated from (and thus made orthogonal to)
constructing classes from other classes (aka derivation). In the *second
step* this takes a big burden from the class hierarchy and makes it
possible to be much more expressive with glueing various bits and pieces
together to create a new class. The great thing is that as soon as
derivation *only* does composition you can treat it as a special case of a
general class of patterns which involve taking pieces of data + functions
and stick them together like lego blocks to build something new.
This kind of pattern is actually quite common nowadays in C++, I believe.
You take a bunch of light-weight classes and combine them as data
representation, algorithm, etc. parts of a bigger class. You add run-time
polymorphism by adding in an ABC which declares the required methods.
My idea would make this last step much more elegant and simple.

-- 
Martin Hinsch

m.hinsch at rug.nl
+31 50 363 8097

CEES Centre for Ecological and Evolutionary Studies
Biologisch Centrum
Kerklaan 30
Postbus 14
9750 AA Haren




More information about the Digitalmars-d mailing list