[comp.object] Inheritance is NOT Delegation

render@casca.cs.uiuc.edu (10/13/89)

I wrote:
> 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.  

I have since found out that the Mach kernel is written in C.
Just goes to show that you shouldn't use examples that you're
not sure about. 

hal.

"Carpe doughnut."

dl@g.g.oswego.edu (Doug Lea) (10/13/89)

Providing assistance in avoiding the confusion between using
inheritence for `isa' relations (vaguely, `subtyping') versus
`part-of' or `implemented-via' (i.e., `uses-code-from') relations
(vaguely, `delegation') is one of the things I think C++ got right. A
problem with some inheritence mechanisms is that there is only one
flavor of connecting arrow between any two classes, that might be
interpreted as `isa', `part-of', `uses-code-from', or anything else,
for that matter.  C++ at least gives two flavors: public inheritence
and private inheritence. The former is nearly always best used when
interpretable as `is a subtype of', and the latter as `is implemented
via'. For example,

class Vehicle { ... }
class Engine  { ... }
class Chassis { ... }
class Wheel   { ... }

Class Car: public Vehicle, private Engine, private Chassis
{
  Wheel  wheels[4];
//...
}

says that a Car is a subtype of Vehicle, implemented via (? -- see
below) an Engine and Chassis.

The exploited difference between public and private inheritence in C++
is that a Car may be used in any situation requiring a Vehicle, but
not in situations requiring an Engine or Chassis, which is exactly
right.

A Car is also implemented via 4 wheels, but I didn't write class Car:
... private Wheel, private Wheel, Private Wheel, private Wheel partly
because C++ wouldn't then let me then distinguish (name) the 4 wheels
individually. But this also shows that I could have just as well
written the whole thing as

Class Car: public Vehicle
{
  Engine  engine;
  Chassis chassis;
  Wheel   wheels[4];
//...
}

to make clear that the engine, etc., are used soley as components
(i.e., part-of relations), and not for general code-sharing (i.e.,
implemented-via relations). 

For better and worse, C++ doesn't force you to adopt any particular
strategy involving public inheritence (isa), private inheritence
(implemented-via), and aggregation of components (part-of). In fact
C++ is not thoroughly coherent in helping you to do The Right Thing
when implementing such schemes.  For example, it isn't at all sensible
to redefine a non-virtual function in a public subclass (this is fine
in a private subclass), but C++ doesn't outlaw this.  Also, it is
sometimes less than natural to create designs where the elements
themselves are `abstract classes' so that, for example, if Engine were
an abstract class you could create a subtype of Car (say, Lincoln)
that contains a subtype of Engine (V8). (C++ forces such things to be
components, not privately inherited, requiring pointers or references
that must be properly initialized, etc.) However, the distinctions may
be used to useful effect in may contexts. Consider designs like


class Stack // a `pure virtual' abstract class for a stack of ints
{
public:
  virtual int  empty() = 0;  
  virtual int  full() = 0;
  virtual void push(int x) = 0;
  virtual int& top() = 0;
  virtual void pop() = 0;
};

class Array 
{ 
//...
  int  capacity() { ... }
  int  reallocate(int newsize) { ... }
//... 
};

class BoundedArrayStack: public virtual Stack
{
protected:
  Array s;
  int   sp;
public:
        BoundedArrayStack(int cap) { ... }
  int   full()  { return sp == s.capacity(); }
  void  push(int x) { if (full()) error("push to full stack"); else ... }
//...
};

class ResizableArrayStack: public virtual Stack, private BoundedArrayStack
{
//...
  int  full() { return 0; }
  void push(int x) { if (BoundedArrayStack::full()) s.reallocate(sp * 2);... }
//...
};

class LinkedList { ... }

class LinkedStack: public virtual Stack
{
  LinkedList l;
//...
};

class TraversableStack : public Stack { ... } // another abstract class

class TraversableLinkedStack: public virtual TraversableStack, 
                              private LinkedStack { ... }

//...


--
Doug Lea, Computer Science Dept., SUNY Oswego, Oswego, NY, 13126 (315)341-2367
email: dl@oswego.edu              or dl%oswego.edu@nisc.nyser.net
UUCP :...cornell!devvax!oswego!dl or ...rutgers!sunybcs!oswego!dl