Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!mailrus!ames!umd5!purdue!i.cc.purdue.edu!j.cc.purdue.edu!pur-ee!uiucdcs!uiucdcsp!johnson
From: johnson@uiucdcsp.cs.uiuc.edu
Newsgroups: comp.lang.c++
Subject: Re: oo definition request
Message-ID: <77300012@uiucdcsp>
Date: 2 Jun 88 02:45:00 GMT
References: <1399@its63b.ed.ac.uk>
Lines: 80
Nf-ID: #R:its63b.ed.ac.uk:1399:uiucdcsp:77300012:000:4461
Nf-From: uiucdcsp.cs.uiuc.edu!johnson    Jun  1 21:45:00 1988


>C++ also allows ad-hoc polymorphism (a.k.a. overloading), by allowing
>redefinition of members in subclasses. Most object-oriented languages do this.

This is not ad-hoc polymorphism.  This is inclusive polymorphism.
Imagine that each object has a field for each of its member functions.
This field contains the function.  While this is not the way C++ is
implemented, it is clearly the way you are supposed to think that it
is implemented, since x.foo() means extract the "foo" field of "x"
and call it.   The variable "x" can contain any subclass of the type
of "x", so this seems to be inclusive polymorphism.

Smalltalk has ad-hoc polymorphism because the variable "x" could have
contained any object that implements the "foo" operation, even if they
belonged to wildly different classes.  The critic could claim that this
is really a form of inclusive polymorphism that is hidden by the fact
that Smalltalk is not statically type-checked.

>It's easy to confuse inclusive polymorphism with subtyping.

I thought Cardelli and Wegner defined inclusive polymorphism to be
equivalent with subtyping?  I think by subtyping you mean subclassing.
It is easy to confuse subclassing with subtyping.  :-)  I have a type
system for Smalltalk in which subclasses are not subtypes.  However,
C++, Trellis/Owl, and Eiffel make them be the same, so lots of people
think that they have to be the same.  Emerald has subtypes but no
inheritance, so there is a little more evidence that subtypes are
not subclasses.  The type of X is a subtype of Y if X can always be
treated as a Y.  Thus, subtypes deal with specification.  Inheritance
deals with implementation.  Naturally, implementation and specification
should be related, which is why so many languages make subclasses be
the same as subtypes, but there is no reason why they HAVE to be
equivalent.

>When members are
>redefined then we also have overloading, even if functions are only
>redefined in subclasses (subtypes) of a given class.
>Another way of looking at this is to say that when a member is
>redefined, it only inherits the type of the corresponding member in
>the superclass, not the definition.

I agree completely.  In fact, in Smalltalk it is not necessary for a
method in a subclass to inherit its type from the superclass, which is 
why subclasses in Smalltalk are not subclasses.  However, inclusive
polymorphism does not prevent functions from being redefined.  It just
says that redefined functions must have types that are compatible with
those of the methods being redefined.

>The languages I've seen with multiple inheritance require each class
>to specify their superclasses.  This means that if overloading
>(ad-hoc polymorphism) is "replaced by multiple inheritance", every case
>of overloading must be anticipated by the program or library developer.

>Does Trellis/Owl have this restriction?  Or does it allow a programmer
>to specify existing classes as subclasses of a new class?

Overloading does not have to be anticipated by the program developer,
but shared interfaces do.  Suppose that I have a graphical object
that is composed of lots of other graphical objects.  I implement
operations to read and write the array that holds these graphical
objects, which in Smalltalk would be at: and at:put:.  Now suppose
that I have a sort routine, which takes an array and a predicate
which imposes a total ordering on the object in the array.  In
Smalltalk I can use that sort routine (which I imagine here to be
an object rather than a method) to sort the graphical objects, since
all it requires is that its input understand the at: and at:put:
messages.  In C++, on the other hand, this graphical object will
have to be a subclass of "Array", but I want it to be a subclass
of "GraphicalObject".  Thus, I need multiple inheritance to make
it be a subclass of both.  Multiple inheritance is not needed as
much in Smalltalk.  It would be needed if you wanted the complex
graphical object to understand ALL the array messages, but it
seems unnecessary if all you need are at: and at:put:.  However,
a language with static type-checking requires multiple inheritance.

I am not knocking static type-checking.  It makes it much easier to
create fast implementations, and languages like C++ are certainly a
lot faster than languages like Smalltalk.  However, you do lose a
bit of flexibility.  Most people are probably willing to pay the
price, but I want to have my cake and eat it, too!