Smalltalk and Python

Alex Martelli aleaxit at yahoo.com
Thu Dec 14 10:39:59 CET 2000


"Tim May" <tcmay at got.net> wrote in message
news:tcmay-19C054.14031113122000 at news.got.net...
    [snip]
> Large, complex apps in LISP and Smalltalk did well without using MI.
>
> I don't want to start a religious war over MI vs. SI vs. SI + mix-ins,
> but I'd say that MI fans have not shown a compelling reason why MI is
> necessary.

I'd go further, and say that implementation-inheritance fans
have never shown a compelling reason why any inheritance AT
ALL is 'necessary' -- and we never will (I'll class myself among
such fans:-), because it is *NOT* _necessary_.  Many complex
LISP applications were programmed without actually using CLOS;
C was used to program complex, successful applications, and has
no inheritance at all; Visual Basic, up to version 6, did not
allow implementation inheritance.  Whatever you can do by
inheriting implementation, you can also do by encapsulating
and delegating, and in some languages it's almost as easy
(in Python, for example, a suitable __getattr__ method may
let you 'transparently delegate' almost as conveniently as
inheritance does).

(This is all about inheriting _implementation_ -- C++, Eiffel,
and other languages yet, merge/confuse the concepts that Java
separates as '<class> extends <class>' [implementation
inheritance] and '<class> implements <interface>' [interface
compliance] -- the issues with the two mechanisms are really
pretty separate, and implementation inheritance is more often
what is meant when unqualified 'inheritance' is discussed).

If inheritance itself is not _necessary_ (just _convenient_),
then, a fortiori, so will multiple inheritance be -- surely
not _necessary_, possibly more _convenient_.

It is not *necessary* for a family to own a car; bicycles,
public transportation, rental, etc, may (perhaps at some
inconvenience) substitute.  A fortiori, ownership of more
than one car by a family is not _necessary_ either; it's
pretty intuitive, in fact, that the added value of each
further car you add to a family's pool of vehicles goes
down as the number of vehicles already in the pool goes
up (the first car adds very significant convenience to the
family's ability to go around; the second one may add a
little less; the third one is probably less important
yet; etc).  Similarly, the added value of MI vs SI (in
terms of _convenience_ -- no _necessity_ involved) is no
doubt lesser than that of SI versus no implementation
inheritance at all.


Say that 2/3 of your objects need/want to delegate some
functionality to one other object; 1/3 of those want to
delegate to two other objects; 1/6 of those want to
delegate to three; and so on.  Say this covers only
those cases of delegation that are well covered by
implementation inheritance (delegating to a unique
and permanent 'base object').

With no inheritance at all, you have to take the (modest)
hit of contain-and-delegate for 66 objects out of 100.

With single inheritance, this goes down to 22 -- a net
gain in 44 cases; with multiple inheritance, it goes
down to 0 -- but the further net gain is only 22, half
of the convenience gain that SI brought over nothing.

(A hypothetical 'dual inheritance' system, where you
can inherit from 0, 1, or 2 bases, but no more than
that, would already cover 18 of those 22 cases...).


That the added-convenience is on a diminishing-returns
curve doesn't imply the ideal stopping point is at
allowing 1 inheritance-of-implementation, of course --
you might as well argue for 0, or, 2.  Or maybe, just
like it happens for family and cars, it would be best
to 'disperse' the design-decision -- let each family
determine how many cars best serve its needs, be it
0, 1, 2, whatever.  Similarly, the designer of each
class is perhaps best-placed to determine how many
other classes it is most convenient for it to inherit
from, rather than having the language designer fix
it in advance for all time...?


Alex






More information about the Python-list mailing list