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!