[comp.lang.eiffel] How to use Inheritance instead of nesting

staff@cadlab.sublink.ORG (Alex Martelli) (08/08/90)

>In general, multiple inheritance is almost never needed.  I have never
>seen a published example of a C++ program using multiple inheritance
>that couldn't be coded just as easily using components instead.  (This

This is a major thesis of T. Cargill, and he's been propounding it at
Usenix and UKUUG; indeed, he has rewritten all published examples of
multiple inheritance in C++, with single inheritance or none at all,
and they're better (see the proceedings of the above conferences).

>is not true for some other systems, such as flavors.)  Sometimes multiple
>inheritance is the best way to think of a problem, but it is grossly misused

I wonder!  Yourdon and Coad, in "Object-Oriented Analysis", claim that
M.I. is no doubt great as a CODING technique, e.g. for C++ 2.0, but for
ANALYSIS ("best way to think of a problem"), they shun it as leading to
unwarranted complication in "modeling the problem space".  If the
analysis theoreticians want MI only in coding, and the coding freaks
want to leave MI for analysis, what does this suggest...?

>in the C++ world.  I would be happy for people to point me to examples of
>multiple inheritance in which it is obviously better than any of the
>design alternatives.

The best cathegory of examples I have seen in books/articles/talks by
Bertrand Meyers, and it has to do with parametric classes with some
constraints on operations which need to be available on the formal
types which are the parameters.  Instead of ad-hoc, weakish expression
of the constraints like in Ada, one can say, for example:
"generic class AVL_TREE of T:COMPARABLE" to express the fact that the
T parameter of AVL_TREE must inherit from COMPARABLE, which presumably
one has already coded as an abstract class specifying the comparison
operator (including some of its semantic constraints, in assertions);
now in the code for AVL_TREE I can invoke the comparison operator on
objects of formal type T.  With MI, this does not really limit what
can be put on an AVL_TREE!  Suppose I have a class WORKSTATION, which
of course has NOT inherited from COMPARABLE, but does have a
SERIAL_NUMBER attribute; I can make a COMPARABLE_WORKSTATION with MI
from WORKSTATION and COMPARABLE, by implementing the comparison as
being done on the serial numbers, and have an AVL_TREE of them for
inventory, look-up, etc.

Of course I *could* do the same by just inheriting from COMPARABLE
and HAVING a field of type WORKSTATION, rather than BEING a workstation;
in general, the IS-A and HAVE-A relations are not as disjoint as one
would think in the first place!  However, I would then have some 
trouble applying other WORKSTATION ops & data structures to them.

I have obviously not yet thought enough about these topics, but it
seems to me they're deeply connected with the dual nature of class
inheritance - inheritance of SPECIFICATIONS for an interface, and of
IMPLEMENTATION... I would welcome a discussion on this, and of MI
in general.

Also think of the practical concerns - maybe there are cases where
MI would not be needed IF one could redesign each and every class
hierarchy from scratch, but MI makes it easier to reuse specs and
code, maybe from vendor-bought hierarchies, WITHOUT redesign...?

-- 
Alex Martelli - CAD.LAB s.p.a., v. Stalingrado 45, Bologna, Italia
Email: (work:) staff@cadlab.sublink.org, (home:) alex@am.sublink.org
Phone: (work:) ++39 (51) 371099, (home:) ++39 (51) 250434; 
Fax: ++39 (51) 366964 (work only; any time of day or night).