From: pk@rwthi3.informatik.rwth-aachen.de (Peter Klein)
Subject: Re: MI - clutching at straws
Reply-To: pk@rwthi3.informatik.rwth-aachen.de
Organization: Lehrstuhl fuer Informatik III, RWTH Aachen, Germany
Date: Tue, 15 Sep 92 14:08:40 GMT

In article 92Sep14151942@Dr_No.mitre.org, eachus@Dr_No.mitre.org (Robert I. Eachus) writes:
>In article <1992Sep9.142434.3940@Urmel.Informatik.RWTH-Aachen.DE> pk@rwthi3.informatik.rwth-aachen.de (Peter Klein) writes:
>
> > Unfortunately, your arguments don't hold in my example, where several
> > extensions of the same base type are combined. The resulting type is
> > essentially the base type augmented by an arbitrary subset of the possible
> > extensions. The problems you mentioned cannot arise in this context.
> > Furthermore, it is pretty awkward to simulate such behaviour without MI.
>
>    But it is exactly that case...the (base) type is extended with lists
>and trees, and then these extensions are combined.  (It is hard not to
>use nasty words to relieve frustration at this point, but I know that
>this is a hard enough to understand mechanisms like type extension and
>inheritance, and the subtile differences in mechanisms discussed here
>tend to rapidly convert any brain into jelly, but bear with me.)
>  
Well, either you didn't understand my example or I didn't understand
yours :). Here's my understanding of what you said: You have some
base type, say X. Now you make up lists and trees which *contain* entries
of type X. Right? But then, neither the list nor the tree class are
subtypes of X. They are containers with no common base class and therefore
cannot be "merged" in my proposal.

The other possibility would be that your base class is a container class
like lists, and then you make subtypes for trees and sets. In this case,
it is first of all doubtful that inheritance should be used at all to
design this (since the inheritance is completely on the implementation
part; this is more likely a simple import). Anyway, if you insist to do
so, you could make a class then which is both a set and a tree. But who
would want to do so?

>    Part of the problem is semantic.  I think Tucker will be glad to
>explain to you how Ada implements multiple inheritance, while most of
>us use MI to mean something other than generic instantiation, but
>Tucker does have a point.  The Ada 9X mechanisms are safer and more
>general than those offered by most instances of MI, but it does
>require more thinking up front by the designer of a mix-in.
>
> > Not true. Inheritance is the more powerful feature. Dynamical binding cannot
> > be done with genericity; you'll never get true polymorphism without
> > inheritance. But I don't think this is the question. Genericity and
> > inheritance both have their uses, and most of the time the design makes
> > clear which of them is appropriate in a given situation. If you think that
> > inheritance is not *really* needed, I can accept that. But my original
> > question was: What do I loose when I have SI only?
>
>     I assume that you left a word out above, since in my post I did
>say that inheritance is sometimes necessary, it is union style
>multiple inheritance that is unnecessary in Ada or any other language
>with sufficiently powerful generic capabilities.
>
Hmm, isn't this exactly what I said? I mean, that MI shouldn't be used to
combine arbitrary classes. Or what do you mean by "union style MI"?

> > In what way does the lack of MI affect the usefulness of the whole
> > inheritance idea? *If* I think extensions of a base type should be
> > done using inheritance, how do I solve the problem of combining
> > independent extensions afterwards?
>
>     You don't.  But in general it is always wrong to combine
>extentions which were not intended to be combined.  Ada 9X will give
>you a choice of several combining styles, and in general the language
>will insure that mixtures which are permitted will work.  However,
>since generics mean that the difference between a combining extension
>and normal single inheritance is a few words, you should honor the
>wishes of the type designer and assume that two types which can't be
>mixed shouldn't be mixed:
>
> [ ..example deleted.. ]
>
Yes and no. It is important to make a distinction between combining
arbitrary extensions and extensions which should not be combined. IMHO,
it is illegal to state that *if* I want to combine extensions, these
possible extensions must be known to the base type. It's a quite
natural situation that I want extensions to be mixable, but I cannot
predict how many extensions there will be.

Another example: In a tree, I have nodes. Every node is member of a node
class. This class determines which attributes the node carries. Now, the
classes are arranged into a hierarchy. I might want to build abstract
syntax trees using this; with node classes for identifiers, statements
(with appropriate subclasses for special statements) and the like.
Now there are obvious occurences of MI in this example: An applied
occurrence of an identifier in an expression is a subclass of identifier
(i.e. carries the "name-of-identifier" attribute) as well as a subclass
of the expression component, say factor (has e.g. a "value" attribute).

I hope this clarifies my point. The writer of the base class for the nodes
doesn't want to know in what way his class will be augmented; i.e. which
node classes there will be and what attributes they have. But still, the
type designer might want these to be combined.

>     If it weren't for the fact that generics are IMHO a much more
>powerful tool than inheritance, I could argue that using generics to
>implement mix-ins is like using a sledgehammer to swat flies.  But
>since Ada has all of the necessary support for generics for other
>reasons, it seems silly to talk about adding MI because maybe someday
>someone will think of an application where classical MI is
>significantly better.  (In my opinion, and that of a lot of other
>software engineers, the ability to express "Watch it!" in the code is
>a definite advantage.  In Ada 9X using inheritance in a non-generic
>fashion will be a strong warning message that this new type has more
>than mix-in semantics.)
>

Sorry, but I still don't see how you handle polymorphism with generics.
One last example on this: Suppose you have some container class, let's
say a list. In this list, you want to store objects of different types.
In the implementation of the list, you don't know what types, you don't
even know how many. In fact, you *shouldn't* know this, because it has
nothing to do with the list itself. Now, please, how do you do this with
generics?

Peter
---
Peter Klein                        E-Mail: pk@rwthi3.informatik.rwth-aachen.de
Lehrstuhl fuer Informatik III      Tel.: +49/241/80-21320
Ahornstrasse 55                    Fax.: +49/241/80-21329
RWTH Aachen
D-5100 Aachen
Germany

Newsgroups: comp.lang.ada