[comp.object] Inheritance is NOT Delagation

render@brutus.cs.uiuc.edu (Hal Render) (10/13/89)

david@jpl-devvax.JPL.NASA.GOV (David E. Smyth) writes:
>1) Inheritance violates encapsulation by the superclasses, therefore
>2) Inheritance makes concurrency more difficult in the resultant system.

Point one is arguable.  If the "violation" you point out is the dependency 
of the structure and behavior of subclass on that of its superclass, then 
I agree that encapsulation has been violated.  However, how is this different
from the dependence between an object that delegates to another object?
In one case you are sharing actual definitions, but behaviorally the 
dependence seems much the same.

As for point two, I'd have to hear a better argument than proof by
statement.

>Note: "Actors" which is the most widely accepted language concept for
>concurrent object programming, DOES NOT support concurrency.

Do you mean Actors doesn't support INHERITANCE?  If not, then the 
above statement does not make sense.  If so, it still is not a proof of (2).

>Using delagation, one builds a complex "object" through grouping
>several different small objects together.  Each small object maintains
>its own address space and thread.  The complex object is only
>conceptual.
>Delagation reflects reality better than inheritance:  your car does not
>inherit from door, tire, and engine: is is a composite made up of
>doors, tires, and an engine.  The fact that the window on the left door
>is open should have no bearing on the state of other windows or the
>fuel injection or tire pressure.

What you have just said makes no sense.  Your confusing a part-of 
relationship (aggregation of subparts into a whole) with a kind-of
relationship (the sharing of common properties by similar objects).
True, there is a similarity in the implementation mechanisms, but the 
conceptual meanings are different.  With your example, the idea of 
inheritance in conceptual modeling of a car is better demonstrated by 
multiple inheritance hierarchies, one for each of the major parts.  
Assuming all connections are compatible, you'd have a specialization 
hierarchy for chassis, engine, door, etc.  Car would be an abstract 
class with abstract components Chassis, Engine, LeftDoor, RightDoor, 
Wheels, etc.  You could then define a concrete subclass of Car with 
concrete component classes.  For example, you might define the SportsCar 
subclass of Car with RacingChassis, TurboEngine, SportWheels and so on 
as concrete component classes.  This is just one way to use inheritance 
and part-of relationships.

>Concurrency is more cleanly supported with Delagation than with
>Inheritance.  Imagine a Car class built using multiple-inheritance.
>Building the car would require the constructors to be invoked serially,
>OR the programmer would have to be concerned about critical sections
>and the like.  As we all know, critical sections are notoriously hard
>to find and debug.  The reason time sharing systems are so easy to use
>is this: all of the processes get their own address space.  The
>encapsulation provided by objects is exactly the same, but the
>granularity is finer.  This leads to more effective use of
>multi-processors and multi-threaded processes (ala Mach).

Concurrency is a function of run-time behavior; inheritance is (mostly)
an issue compile-time structure.  Concurrent message-passing is done
between instances whose structure has already determined and which have
their own local storage, so how that structure was determined is a null
issue.  Or do you think that inheritance means you share data slots with 
your parent?  If so, maybe you have the wrong idea about inheritance.

BTW, I believe they used Objective C to code Mach, and I'm pretty sure
that Objective C has inheritance.  Of course, the conceptual model of 
the language that you code a system in and the conceptual of the system
are two different things, but it just shows that inheritance isn't
totally worthless.  

>In fact, one can think of the object universe which represents the
>typical object-oriented application as being a bunch of delagating
>objects.

Yes, but I think that this is because delegation is a more primitive 
mechanism than inheritance.  Although I don't know if it has been tried,
you can probably show that you could implement inheritance with
delegation.  Of course, you can implement delagation with a Turing machine,
but this doesn't mean I want to program using one.

>The average depth of inheritance in most systems is about 3.  The
>number of object types in many systems is very large, in the dozens to
>thousands.  Therefore, people tend to favor delagation over inheritance
>by a large margin, even when they don't consider it to be an issue.

I'm curious where you that number.  I don't necessarily disbelieve it, 
I just wonder where it came from, since  I'd be surprised for large 
systems written in class-oriented languages to have such a shallow tree.
Still, the part-of relationship is as important as the kind-of relationship
so it wouldn't suprise me overly much.

>Can you imagine the nightmare which would result if all the objects in
>YOUR application were cobbled together via inheritance into a single
>object type?  Barfo dude!  Sure, a graduate student can "prove", that
>"Inheritance IS Delagation" but is is obviously the inferior form of
>the duality.

What wrong with treating a collection of objects as an instance of
a single class?  That seems to be your implication.  Sure, a car is 
a collection of parts, but you can have more than one car, each with 
its own engine, doors, wheels and chassis, so it seems logical to 
have a class Car to describe many instances of an aggregation of parts.
I think a programming language would be inferior that made me do more work
than another to implement a useful modeling concept, namely inheritance
and the kind-of relationship.  Delegation is nice, but I don't think
it proves inheritance to be an unsound concept. 

>Lynn Stein would have met with alot of disagreement if that paper was
>presented at OOPSLA '89.

Possibly, but I hope it would have been from people who had read it 
and had reasonable arguments.  Perhaps you should give it a read, dude.

hal.

ballou@nebula.ACA.MCC.COM (Nat Ballou) (10/13/89)

From article <1989Oct13.020914.2811@brutus.cs.uiuc.edu>, 
by render@brutus.cs.uiuc.edu (Hal Render):
>>david@jpl-devvax.JPL.NASA.GOV (David E. Smyth) writes:

>>The average depth of inheritance in most systems is about 3. 
>>...

> I'm curious where you [found] that number.  I don't necessarily disbelieve 
> it, I just wonder where it came from, since I'd be surprised for large 
> systems written in class-oriented languages to have such a shallow tree.
> ...
> hal.

Don't believe it.  On the Lisp machine, the depth of the tree with root
SI:STREAM is at least 10 levels deep.  Also, I have seen object-oriented
databases with depths greater than 10.  I'm not familiar with SmallTalk, 
but I'd bet the class library is deeper than 3 in parts.  Any takers?

johnson@p.cs.uiuc.edu (10/14/89)

>I'm not familiar with SmallTalk, 
>but I'd bet the class library is deeper than 3 in parts.  Any takers?

Object
  Controller
    MouseMenuController
      ScrollController
        ParagraphEditor
          TextController
            CodeController

However, I don't think that ScrollController should be in the hierarchy,
since I think that scrolling should be reused by components, not by
inheritance.  Moreover, it is not clear that one should count Object.
Even with this caveat, the class library is a lot deeper than 3.

Ralph Johnson

jans@tekgvs.LABS.TEK.COM (Jan Steinman) (10/14/89)

<david@jpl-devvax.JPL.NASA.GOV (David E. Smyth)>
<The average depth of inheritance in most systems is about 3.>

This is somewhat ambiguous.  How is "average depth" defined?

1) Do you mean the number of subclasses divided by the sum of their depths?  
That would be somewhat misleading, as the class chain "Object, Set, Dictionary, 
IdentityDictionary, MethodDictionary" would have an average depth of 2.5, but 
this does not address the usefulness and instance counts of each class.

2) If you mean the number of objects in the system divided by the sum of their 
depths, than I would suspect that Smalltalk-80, at least, is *much* deeper than 
3, since instances tend to be of leafs, rather than of more abstract classes 
somewhere higher up.

3) If you mean the average height that an instance must go up the superclass 
chain at run time in order to locate a desired method, then 3 is too high, at 
least in Smalltalk.  Most methods sent to a Smalltalk object are in it's own 
method dictionary.

No, I don't have numbers right now.  Case #1 and #2 numbers would be easy to 
obtain in a workspace for a given Smalltalk image.  I think the Green Book 
discussion on the Smalltalk interpreter  method cache has some numbers for #3.

							   Jan Steinman - N7JDB
						  Electronic Systems Laboratory
					Box 500, MS 50-370, Beaverton, OR 97077
						(w)503/627-5881 (h)503/657-7703