On multiple inheritance

Hans-Dieter Dreier Ursula.Dreier@ruhr-uni-bochum.de
Tue, 08 Dec 1998 03:02:17 +0100



Matthew Tuck schrieb:

> > Do you have a refence where I can read something about that? At first
> > sight I can't see how that could solve the problem, given that you
> > just have *two* ends but *multiple* inheritance.
>
> I took a look.  The principle is that you can do MI in a closed-class
> system given that you are willing to waste some space, e.g.
>
>                         *
> a:                      abc
> b extends a:            abcdef
> c extends a:            abc   ghi
> d extends b,c:          abcdefghi
>
> Whereas in two directional it's:
>                         *
> a:                      abc
> b extends a:            abcdef
> c extends a:         ghiabc
> d extends b,c:       ghiabcdef
>
> Algorithms can determine at compile-time an efficient layout, and
> two-directional layout improves the wasted space.  In looking through it
> it could only be of limited use in systems where classes are not fixed
> at  compile time.

That is what I would expect. It would mean that you couldn't compile a class without looking
at its siblings and descendants, which would not be good for incremental compilation. Also,
this is just a relief for the waste of space, not a cure. Anyway, it adds complexity which is
not a good thing in itself.

> > You mean you implement parts of a merged specification in one and
> > other parts in another class?  How is that merging of specifications
> > supposed to work?
>
> No the implementation is merged.  The specification stays the same.

Can you give an example?

> I'm not sure what you meant by constructors merging in C++.

The calls will be nested in some manner which is not obvious until you look at it in detail.

> >> There's no subtyping here either, which is why I don't like this.
> > Please explain. I don't understand what you mean.  class Employed (class Person pE) {};
>
> Ok, I'm getting a little confused.  Would you be able to give a full
> example of a Person, Customer, Employed and Employed Customers?  Then I
> might be able to comment a bit further.

I can't explain it in C++ because C++ doesn't have that sort of construct.A class parameter
(class Person pE, in the above example) would behave the same way a function parameter
behaves in a function: It is passed to the class when that is instantiated and becomes sort
of a (constant) instance variable then. Also, it is part of the type system which has to
match (similar to parameter types of a function, which affect the type of a function pointer,
making an int (*func) (int) different from an int (*func) (int, int). I hope I got that
declaration correct.

pE would be the name of the parameter inside the class. And you could pass it on as a class
parameter the same way you could do with every variable. The type of the parameter the caller
passes in must be determinable at compile time, exactly like a function argument.

> > > This seems to me to be getting back to the exact same system of rank
> > > with multiple inheritance, except you don't have subtyping.
> > But it's more obvious to the user, and because of normal inheritance
> > rules you got an "override" relationship instead of name clashes.
>
> I'm trying to put my finger on exactly what I don't like about it.  I
> think it's partly that you were saying you have Employed Customer
> Persons and Customer Employed Persons.  These might be valuable concepts
> at the implementation level but at the specification level you want just
> one to avoid complicating things.  Could you assign one to the other for
> example?

No, I don't think so. It would have to be converted to a Person first by retrieving the
parameter, which could be done by an automatic type conversion, but the Customer (or
Employed) part would be lost. I admit, this might be a problem sometimes. But I suppose it's
the price you have to pay in order to get the inheritance structured hierarchically.

> ... separation of code inheritance from specification
> inheritance, etc.

Can you explain that?

> One thing I just thought of which I'd been trying to think of a solution
> to before - inherited assertions (precons, postcons, invariants) go in
> the specification, while implementation specific assertions go in the
> implementation.

Good idea.

> It's true that most of this sort of thing can be done using subclasses,
> but enforcing it allows increased flexibility since it enforces the
> regime upon you.  From a logical point of view they are separate after
> all.  An intelligent editors can help with stuff like creating the
> template of a new implementation, for those worrying about extra typing.

It might also provide a "view" of a class where only the specification part is visible
although the implementation is present as well. At any rate, I would like to avoid the
overhead of having to declare the things specified by the specification a second time when it
comes to implementing. That's exactly the sort of tedious work I always hated in C, and prone
to typos as well. Maybe the editor can generate sort of a template where all those parts
inherited from the specification would be noneditable.

> The most serious problem I see with MI
> is its implementation.

So do I.

>  That's the part I know the least about and we
> need to find out about it.  At the langauge level I think your concerns
> can be addressed.

Agreed.