[comp.sys.mac.programmer] Multiple Inheritance -- Is It A Luxury?

tim@efi.com (Tim Maroney) (07/03/90)

The people doing the MPW compilers seem to think that multiple
inheritance is not important.  It's not possible at all in Object
Pascal, and apparently is impossible to use in real (handle-based)
applications in C++.  I think this is a cavalier attitude.  I've only
been using Object Pascal for a couple of months now, and my only
earlier OOP experience was with a flavored dialect of Franz Lisp many
years ago; but I have already encountered a number of cases where the
lack of multiple inheritance imposes inelegant solutions.  The
"seaplane" analogy seems to be a frivolous way of dismissing this
important technique.

First case:  Extending a class library.  Suppose that programmer A adds
good, general Windows menu support to MacApp.  There are basically two
ways of doing this.  The first is to create a class library add-on
providing a number of methods which are supposed to be called at
various points in other deveopers' applications.  The other is to
create a subclass of TApplication that calls all these methods at the
appropriate places.  In the first solution, the developers using this
code have a considerably greater burden in terms of
documentation-reading and error avoidance and code modification; in the
second solution, developers only need to make their applications
sub-classes of the sub-classed TApplication, a one-word code change.
Obviously the second solution is cleaner.

But now suppose someone else takes the same approach to add, say,
walk-through keyboard-oriented menus.  OOPs!  You can't make your
application a subclass of *both* TWinMenuApplication and
TWalkMenuApplication.  There's no multiple inheritance.  One or the
other has to revert to the bad old "insert tab A into routine B"
solution.

Second case:  Managing a list of largely dissimilar objects that have
some common behavior.  For instance, suppose that you are keeping a
list of objects, some of which are TViews, some of which are TCommands,
some of which are on your own inheritance tree from TObject.  They
can't be given common methods, because you can't make something a
descendant of both TView and your common-methods class.  Multiple
inheritance would make for a very clean solution.  Instead, you have to
put in type-coercion case statements using class ids, or have each list
entry associated with a separate object sub-classed on a
per-list-element-type basis which implements the common methods while
knowing what type of object the message is being passed on to.  Both of
these are very clunky solutions to a problem which is cleanly solved by
multiple inheritance.

If I were in the languages groups at either Apple or Symantec, I
would consider it a high priority to bring multiple inheritance into
Object Pascal and to make it usable with C++ or Object C.  Elegant
solutions are not a luxury.  Clean code is more maintainable and less
buggy.  If someone has a personal dislike of multiple inheritance and
doesn't want to use it, fine.  Adding it to the language imposes no
such burden on these people.  But omitting it does impose a burden
on those of us in the other camp.

casseres@apple.com (David Casseres) (07/04/90)

In article <1990Jul2.181147.1672@efi.com> tim@efi.com (Tim Maroney) writes:
> The people doing the MPW compilers seem to think that multiple
> inheritance is not important.  It's not possible at all in Object
> Pascal, and apparently is impossible to use in real (handle-based)
> applications in C++.  I think this is a cavalier attitude.

One clarification and two comments.  The clarification:  C++ on the Mac 
does not allow multiple inheritance for subclasses of THandleObject; but 
it can be used with all other classes.  It doesn't matter whether the 
application uses THandleObject subclasses in addition.  Note that it is 
not necessary for everything to be handle-based.

First comment:  The restriction on THandleObject subclasses and multiple 
inheritance is due to serious implementation difficulties that have been 
explained in this group, not to a cavalier attitude.

Second comment:  There is some justification for a cavalier attitude about 
multiple inheritance, just as there is justification for wanting it very 
badly in some cases.  Brian Bechtel sums it up very well in saying 
"Multiple inheritance is the GOTO of the 1990's."  It is tremendously 
powerful, lets you do any damn thing you like, elegantly solves certain 
problems, leads to utterly obscure code, and invites massive abuse that 
can cause enormous damage to the integrity of code.

In my own limited experience with C++, I have found that a redesign of the 
hierarchy always leads to cleaner, more elegant code than multiple 
inheritance.  But then, I'm not using a hierarchy containing a lot of 
libraries produced by other people.  If I were, I might want to use a lot 
of multiple inheritance; but on the other hand, I think that in that 
situation what I would *really* want is source code for all the libraries 
so I could re-implement them to suit my purposes!  That, not any lack of 
features, is the problem with any OOPS that gives you only compiled 
libraries instead of source code.

David Casseres
     Exclaimer:  Hey!

rmh@apple.com (Rick Holzgrafe) (07/04/90)

In article <8967@goofy.Apple.COM> casseres@apple.com (David Casseres) 
writes:
> [...] I'm not using a hierarchy containing a lot of 
> libraries produced by other people.  If I were, I might want to use a 
lot 
> of multiple inheritance; but on the other hand, I think that in that 
> situation what I would *really* want is source code for all the 
libraries 
> so I could re-implement them to suit my purposes!

Well, I like source too. But one of the best features of OOP is re-usable 
modules *without* having to hack the source.

==========================================================================
Rick Holzgrafe              |    {sun,voder,nsc,mtxinu,dual}!apple!rmh
Software Engineer           | AppleLink HOLZGRAFE1          rmh@apple.com
Apple Computer, Inc.        |  "All opinions expressed are mine, and do
20525 Mariani Ave. MS: 77-A |    not necessarily represent those of my
Cupertino, CA 95014         |        employer, Apple Computer Inc."

lins@Apple.COM (Chuck Lins) (07/04/90)

In article <8967@goofy.Apple.COM> casseres@apple.com (David Casseres) writes:
[ a lot of commentary deleted; perhaps relevant ]
>Brian Bechtel sums it up very well in saying 
>"Multiple inheritance is the GOTO of the 1990's."  

I couldn't agree more. Eventually some big name CS prof will probably write an
article called "Multiple Inheritance Considered Harmful". There'll be a big,
huge, mundo flame war over it. If people go ga-ga over MI the way they have so
far with objects, we'll end up with "spagetti-objects" even worse than the
spagetti code produced using GOTO. (An even worse construct was COBOL's ALTER
verb but we won't get into that! :) Don't get me wrong, I think the object-
oriented paradigm has a lot to offer and is one of the more valuable techniques
in the programmer's arsenal to come around in years. But I was a neophyte
programmer during the 'structured programming revolution'. And all the claims
of 'object-this' and 'object-that' sound very similar to the 'structured-this'
and 'structured-that' of the 1970's. Lots of hype and claims that can't be
substantiated. So I know I'd love to see any empirical evidence that shows
MI reduces not only new development costs but also the cost of maintenance.
Please post your references to those journal articles today 'cause I'd love to
be enlightened.


-- 
Chuck Lins               | "Is this the kind of work you'd like to do?"
Apple Computer, Inc.     | -- Front 242
20525 Mariani Avenue     | Internet:  lins@apple.com
Mail Stop 37-BD          | AppleLink: LINS@applelink.apple.com
Cupertino, CA 95014      | "Self-proclaimed Object Oberon Evangelist"
The intersection of Apple's ideas and my ideas yields the empty set.

casseres@apple.com (David Casseres) (07/04/90)

[I wrote]
> ...C++ on the Mac does not allow multiple inheritance for subclasses
> of THandleObject...

Sloppy, sloppy.  I should have said "for subclasses of HandleObject or 
PascalObject." 

David Casseres
     Exclaimer:  Hey!

amanda@mermaid.intercon.com (Amanda Walker) (07/04/90)

In article <42616@apple.Apple.COM>, lins@Apple.COM (Chuck Lins) writes:
> If people go ga-ga over MI the way they have so
> far with objects, we'll end up with "spagetti-objects" even worse than the
> spagetti code produced using GOTO.

There are times when multiple inheritance can be used to produce very elegant
code.  However, object-oriented programming doesn't enforce disciplined
programming any more than anything else.  Used properly, multiple inheritance
can be very useful in decomposing problems over orthgonal axes (for example,
take a look at the "mixin" concept in several Lisp object platforms).  Used
improperly, you can end up with the "it's a floor wax AND a dessert topping"
effect...

It all depends on the programmer.
--
Amanda Walker
InterCon Systems Corporation
--
"I can only assume this is not the first-class compartment."
	--Hitchhiker's Guide to the Galaxy

lins@Apple.COM (Chuck Lins) (07/06/90)

In article <2691908E.738C@intercon.com> amanda@mermaid.intercon.com (Amanda Walker) writes:
>In article <42616@apple.Apple.COM>, lins@Apple.COM (Chuck Lins) writes:
>> If people go ga-ga over MI the way they have so
>> far with objects, we'll end up with "spagetti-objects" even worse than the
>> spagetti code produced using GOTO.
>
>There are times when multiple inheritance can be used to produce very elegant
>code.  
	And there are times when I can use assembly language and the evil GOTO
	to write very elegant code too.

>Used properly, multiple inheritance
>can be very useful in decomposing problems over orthgonal axes (for example,
>take a look at the "mixin" concept in several Lisp object platforms).  Used
>improperly, you can end up with the "it's a floor wax AND a dessert topping"
>effect...
	Symbolic Lisp Machines have a wonderful class in the UI called a
	Listener. It inherits from 26 different classes, sometimes through
	multiple different paths in the inheritance graph. It's impossible
	to subclass properly or even figure out how to take advantage of its
	functionality (in case one wanted to do the same thing).



-- 
Chuck Lins               | "Is this the kind of work you'd like to do?"
Apple Computer, Inc.     | -- Front 242
20525 Mariani Avenue     | Internet:  lins@apple.com
Mail Stop 37-BD          | AppleLink: LINS@applelink.apple.com
Cupertino, CA 95014      | "Self-proclaimed Object Oberon Evangelist"
The intersection of Apple's ideas and my ideas yields the empty set.

tim@efi.com (Tim Maroney) (07/06/90)

In article <1990Jul2.181147.1672@efi.com> tim@efi.com (Tim Maroney) writes:
>> The people doing the MPW compilers seem to think that multiple
>> inheritance is not important.  It's not possible at all in Object
>> Pascal, and apparently is impossible to use in real (handle-based)
>> applications in C++.  I think this is a cavalier attitude.

In article <8967@goofy.Apple.COM> casseres@apple.com (David Casseres) writes:
>One clarification and two comments.  The clarification:  C++ on the Mac 
>does not allow multiple inheritance for subclasses of THandleObject; but 
>it can be used with all other classes.  It doesn't matter whether the 
>application uses THandleObject subclasses in addition.  Note that it is 
>not necessary for everything to be handle-based.

I haven't used the C++ MacApp, but isn't it handle-based?

>First comment:  The restriction on THandleObject subclasses and multiple 
>inheritance is due to serious implementation difficulties that have been 
>explained in this group, not to a cavalier attitude.

Not really.  I have yet to run into a programming model using pointers
into nonrelocatable blocks that couldn't be rephrased in terms of
offsets into relocatable blocks.  It may require some work on the part
of the compiler developer -- since they didn't do it right the first
time -- but it's hardly a serious implementation difficulty.  It's a
well-known programming practice.

>Second comment:  There is some justification for a cavalier attitude about 
>multiple inheritance, just as there is justification for wanting it very 
>badly in some cases.  Brian Bechtel sums it up very well in saying 
>"Multiple inheritance is the GOTO of the 1990's."  It is tremendously 
>powerful, lets you do any damn thing you like, elegantly solves certain 
>problems, leads to utterly obscure code, and invites massive abuse that 
>can cause enormous damage to the integrity of code.

Hmm.  Power can always be abused.  The more power you give a developer,
the more power she has to write either elegant or inelegant code.  There
are very few cases in which the power of a GOTO leads to cleaner code
(certain software implementations of finite-state machines are all that
springs to mind), but I don't think that multiple inheritance is one of
these inherently risky powers.

Writing a better programming language is a matter of psychology.  How
cleanly do the programming language's concepts and tools map into the
way that humans inherently view objects and tasks?  A loop construct is
closer to the ordinary human way of seeing tasks than is a GOTO.  If
we're telling soemone how to do something, we might say "do this ten
times" or "keep doing it until the film is dry" or something of that
kind; we are much less likely to say "go back to step 5".

Object programming is another step towards more human conceptualization
of tasks.  The whole notion of class inheritance is based on the human
division of phenomena into categories and subcategories.  Because of
this, object programming can lead to solutions that seem more "natural"
and "clean".  But humans also naturally perceive categories in terms of
multiple inheritance; that is, many phenomena are routinely considered
members of classes which are not descendants of each other.  Because of
this, multiple inheritance is a step closer to human concepts, unlike
GOTO which is an artificial contrivance unrelated to normal human modes
of perception.  So I don't think the a comparison between multiple
inheritance and GOTO is accurate.  If anything, they are opposites.

>In my own limited experience with C++, I have found that a redesign of the 
>hierarchy always leads to cleaner, more elegant code than multiple 
>inheritance.  But then, I'm not using a hierarchy containing a lot of 
>libraries produced by other people.  If I were, I might want to use a lot 
>of multiple inheritance; but on the other hand, I think that in that 
>situation what I would *really* want is source code for all the libraries 
>so I could re-implement them to suit my purposes!  That, not any lack of 
>features, is the problem with any OOPS that gives you only compiled 
>libraries instead of source code.

I don't agree.  You shouldn't have to modify source code to use an
object library.  It leads to an immediate drop in confidence in the
code's reliability, which is to say, when you get a bug, you never know
whether it's because of code you've added or because of the changed
object library.  It's possible that you've violated subtle assumptions
of the library, so you have to spend a great deal of time just plowing
through source code that you should never need to see.

If I have one big complaint with MacApp so far, it is precisely that
you have to read the source code all the time.  If you have to change
the code to do things, then this problem gets even worse.

tim@efi.com (Tim Maroney) (07/06/90)

In article <8967@goofy.Apple.COM> casseres@apple.com (David Casseres) writes:
>>Brian Bechtel sums it up very well in saying 
>>"Multiple inheritance is the GOTO of the 1990's."  

In article <42616@apple.Apple.COM> lins@Apple.COM (Chuck Lins) writes:
>But I was a neophyte
>programmer during the 'structured programming revolution'. And all the claims
>of 'object-this' and 'object-that' sound very similar to the 'structured-this'
>and 'structured-that' of the 1970's. Lots of hype and claims that can't be
>substantiated. So I know I'd love to see any empirical evidence that shows
>MI reduces not only new development costs but also the cost of maintenance.
>Please post your references to those journal articles today 'cause I'd love to
>be enlightened.

You would?  Fine, then read my message, and if you can come up with
cleaner solutions to the two problems I described in detail there,
solutions that require neither multiple inheritance nor modification of
object library source code, by all means post your enlightened,
empirical rebuttal.

If you can't come up with good non-MI, non-source-code-changing
solutions, though, then please don't just pretend that the examples
don't exist.  Ignoring counterexamples is definitely not any kind of
empiricism that *I* know of....

shebanow@Apple.COM (Andrew Shebanow) (07/06/90)

In article <1990Jul2.181147.1672@efi.com> tim@efi.com (Tim Maroney) writes:
>The people doing the MPW compilers seem to think that multiple
>inheritance is not important.  It's not possible at all in Object
>Pascal, and apparently is impossible to use in real (handle-based)
>applications in C++.  I think this is a cavalier attitude.  I've only
>been using Object Pascal for a couple of months now, and my only
>earlier OOP experience was with a flavored dialect of Franz Lisp many
>years ago; but I have already encountered a number of cases where the
>lack of multiple inheritance imposes inelegant solutions.  The
>"seaplane" analogy seems to be a frivolous way of dismissing this
>important technique.

Although it might seem hard to believe given the inflammatory tone
of Tim's missive, there are many people here at Apple who think
that MI is important. I suggest that you all read the article by
David Goldsmith and Jack Palevich in the latest issue of
d e v e l o p for some useful MI guidelines that we use internally.

The limitations on the use of MI in handle based objects are caused
by C++'s object model, and not by a lack of concern on the part
of Apple's engineers. If anyone can figure out a good way to solve
this problem without rewriting all of CFront, we would of course be
very interested in hearing about it.

Object Pascal doesn't support MI primarily for historical reasons.
The language wasn't designed with MI in mind, and adding MI
to it would be a decidedly non-trivial change. However, Apple's
Advanced Technology Group is looking at doing an updated
version of the Object Pascal language - for more information,
see the last issue of the MacApp Developer's Association publication,
Frameworks".

Andy Shebanow
Apple Computer, Inc.

amanda@mermaid.intercon.com (Amanda Walker) (07/06/90)

In article <1990Jul5.223032.14604@efi.com>, tim@efi.com (Tim Maroney) writes:
> I have yet to run into a programming model using pointers
> into nonrelocatable blocks that couldn't be rephrased in terms of
> offsets into relocatable blocks.  It may require some work on the part
> of the compiler developer -- since they didn't do it right the first
> time -- but it's hardly a serious implementation difficulty.

In the abstract, you're quite right.  However, C++ is a little trickier,
thanks (?) to it's heritage from C.  In particular, object references
are generally treated as being "special" kinds of pointers.  Technically,
I don't see anything in the language that requires that object references
and pointers be the same size, but I suspect that it would be extremely
difficult to retrofit such a change into an existing C++ compiler such
as cfront (which is what Apple's C++ is based on).

Now, I'm all for a from-scratch C++ compiler--one that could handle 64-bit
object references and spit out object files instead of C code, but I'd
rather have a solid port of cfront to play with until such a beast
exists.  Even what we've already got is a noticeable improvement over
vanilla C...

--
Amanda Walker <amanda@intercon.com>
InterCon Systems Corporation
--
"I can only assume this is not the first-class compartment."
	--Hitchhiker's Guide to the Galaxy

lbaum@bcsaic.UUCP (Larry Baum) (07/06/90)

In article <42665@apple.Apple.COM> lins@Apple.COM (Chuck Lins) writes:
: 
: >Used properly, multiple inheritance
: >can be very useful in decomposing problems over orthgonal axes (for example,
: >take a look at the "mixin" concept in several Lisp object platforms).  Used
: >improperly, you can end up with the "it's a floor wax AND a dessert topping"
: >effect...
: 	Symbolic Lisp Machines have a wonderful class in the UI called a
: 	Listener. It inherits from 26 different classes, sometimes through
: 	multiple different paths in the inheritance graph. It's impossible
: 	to subclass properly or even figure out how to take advantage of its
: 	functionality (in case one wanted to do the same thing).

It might be impossible for you, but it certainly isn't in general.  I
think the key point is that without multiple inheritance, Symbolics
probably wouldn't have come up with this class which you admit is
wonderful.

The flavor components of Lisp-Listener are:

W:LISP-LISTENER
  W:LISTENER-MIXIN
    W:INTERACTOR-MIXIN
    W:LISTENER-MIXIN-INTERNAL
      W:PROCESS-MIXIN
      SI:STANDARD-VALUE-ENVIRONMENT-MIXIN
  W:WINDOW
    W:BORDERS-MIXIN
    W:LABEL-MIXIN
      W:ESSENTIAL-LABEL-MIXIN
        W:MARGIN-HACKER-MIXIN
    W:MINIMUM-WINDOW
      W:ESSENTIAL-EXPOSE
      W:ESSENTIAL-ACTIVATE
      W:ESSENTIAL-SET-EDGES
      W:ESSENTIAL-MOUSE
    W:STREAM-MIXIN
      SI:DISPLAY-INPUT-EDITOR
        SI:INTERACTIVE-STREAM
          SI:LINE-OUTPUT-STREAM-MIXIN
          SI:CHARACTER-STREAM
          SI:BIDIRECTIONAL-STREAM
            SI:INPUT-STREAM
    W:SELECT-MIXIN
    W:GRAPHICS-MIXIN
      W:ESSENTIAL-WINDOW
        W:SHEET
          SI:OUTPUT-STREAM
            SI:STREAM
      GRAPHICS:RASTER-GRAPHICS-MIXIN
        GRAPHICS::DRAWING-STATE-GRAPHICS-MIXIN
          GRAPHICS:STANDARD-GRAPHICS-MIXIN
      W:GRAPHICS-COMPATIBILITY-MIXIN
  FLAVOR:VANILLA

Without going thru each one individually, each of these mixins provides
different sets of behaviors which are for the most part orthogonal; e.g.
Listener-mixin makes the lisp listener a separate process with a
READ-EVAL-PRINT loop and the ability to understand command processor
commands.

Borders mixin takes care of how and when to draw or redraw borders on
windows, label-mixin takes care of window labels, etc.

It is true that often a method (i.e. the function that runs in response
to a message) is a complex combination of individual methods contributed
from each mixin and it can be difficult (but certainly not impossible)
to figure out how they combine.  That is why Symbolics includes a
workbench of extremely powerful tools such as the Flavor Examiner,
Inspector, etc.  I would certainly agree that object-oriented languages
permitting multiple inheritance should be bundled with such powerful
tools.  Of course, it is multiple inheritance that makes the building
of those tools much more feasible.

-- 
Larry Baum
Advanced Technology Center              
Boeing Computer Services     uucp:       uw-beaver!bcsaic!lbaum
(206) 865-3365               internet:   lbaum@atc.boeing.com       

dorner@pequod.cso.uiuc.edu (Steve Dorner) (07/07/90)

In article <1990Jul5.223032.14604@efi.com> tim@efi.com (Tim Maroney) writes:
>A loop construct is
>closer to the ordinary human way of seeing tasks than is a GOTO.  If
>we're telling soemone how to do something, we might say "do this ten
>times" or "keep doing it until the film is dry" or something of that
>kind; we are much less likely to say "go back to step 5".

As long as we're waxing philosophical:

I think I'm far more likely to tell someone, "if the film isn't dry,
do it again."  And "start over from the beginning" is also very common.
Both of these are very much GOTO's.

I think loops and such are in fact very UNnatural. They take quite a bit
of getting used to, which is not a comment on their utility or elegance.
The same may be said of OOPL's; they're darn weird at first.


--
Steve Dorner, U of Illinois Computing Services Office
Internet: s-dorner@uiuc.edu  UUCP: {convex,uunet}!uiucuxc!dorner

lsr@Apple.COM (Larry Rosenstein) (07/07/90)

In article <1990Jul2.181147.1672@efi.com> tim@efi.com (Tim Maroney) writes:
>
>First case:  Extending a class library.  Suppose that programmer A adds
>good, general Windows menu support to MacApp.  There are basically two
>ways of doing this.  The first is to create a class library add-on
>providing a number of methods which are supposed to be called at
>various points in other deveopers' applications.  The other is to

That's how I would do this in the context of MacApp.  I would also, provide
a subclass of TApplication that uses these call, for programmers that can
take advantage of it.  (Look at the graphics building block that I
implemented in "Programming with MacApp".) 

>application a subclass of *both* TWinMenuApplication and
>TWalkMenuApplication.  There's no multiple inheritance.  One or the

Multiple inheritance doesn't automatically solve this problem.  There can be
conflicts between the base classes, which the programmer has to resolve.  In
those cases, you are back to the first alternative above (essentially).

>Second case:  Managing a list of largely dissimilar objects that have
>some common behavior.  For instance, suppose that you are keeping a

You can never manage lists of totally dissimilar objects.  The objects must
have some commonality, otherwise you are foced to test their type when you
take them out of the collection.  In a typed language, this means that they
have a common base class.  (In an untyped language such as Smalltalk, 2
classes can implement the same protocol without being related in the class
hierarchy.)

>descendant of both TView and your common-methods class.  Multiple
>inheritance would make for a very clean solution.  Instead, you have to
>put in type-coercion case statements using class ids, or have each list
>entry associated with a separate object sub-classed on a
>per-list-element-type basis which implements the common methods while
>knowing what type of object the message is being passed on to.  Both of

Let's suppose you're doing an interface builder program, so you want to make
a list of the interface objects in the program (views, commands, etc.)

It's not clear that MI makes for a cleaner solution.  You define a
InterfaceElement class and subclass View, Command, etc. to mixin
InterfaceElement.  But you still have the problem that the only things you
can do to the object when you take it out of the list are the method defined
in InterfaceElement.  Suppose InterfaceElement has A Draw() method.  That's
fine, but it means that you have to override Draw for each of the subclasses
that you create.  

This isn't much different from defining subclasses of InterfaceElement such
as ViewElement, CommandElement, ... each of which contains a reference to
the View, Command, ...  You have to define the same number of classes, and
methods although you do end up with twice the number of objects.  In some
sense it is cleaner because the objects that relate to the interface builder
are separate from the objects that are implementing the interface.  Also,
you can use C++ operator overloading to make the use of the surrogate
objects easier.  (ViewElement can define operator View, for example.)

In both implementations, you have to do coercions when you remove an object
from the list, if you want to use any methods defined by View, Command, etc.

>doesn't want to use it, fine.  Adding it to the language imposes no
>such burden on these people.  But omitting it does impose a burden

This isn't necessarily true.  In the standard C++ implementation (as you get
from AT&T) you pay some of the cost of MI, even if you don't use it.  All
the virtual tables are twice as large, and the method dispatching protocol
takes MI into account even if you don't use it.  That's why MPW C++ has a
built-in SingleObject class, which implements the old (CFront 1.2)
dispatching scheme.

I'm sure one could design a runtime system that implements MI without
creating pointers to the middle of an object (and thereby allowing
HandleObjects to use MI), and without placing a runtime burden on
programmers than don't use MI.  This is a big job, however, especially if
you want to maintain semantic compatibility with AT&T's implementation of
C++.  (You have to worry about object casts, and virtual base classes, for
example.) 

-- 
		 Larry Rosenstein,  Object Specialist
 Apple Computer, Inc.  20525 Mariani Ave, MS 46-B  Cupertino, CA 95014
	    AppleLink:Rosenstein1    domain:lsr@Apple.COM
		UUCP:{sun,voder,nsc,decwrl}!apple!lsr

beard@ux1.lbl.gov (Patrick C Beard) (07/08/90)

In article <2691908E.738C@intercon.com> amanda@mermaid.intercon.com (Amanda Walker) writes:
#In article <42616@apple.Apple.COM>, lins@Apple.COM (Chuck Lins) writes:
#> If people go ga-ga over MI the way they have so
#> far with objects, we'll end up with "spagetti-objects" even worse than the
#> spagetti code produced using GOTO.
#
#There are times when multiple inheritance can be used to produce very elegant
#code.  However, object-oriented programming doesn't enforce disciplined
#programming any more than anything else.  Used properly, multiple inheritance
#can be very useful in decomposing problems over orthgonal axes (for example,
#take a look at the "mixin" concept in several Lisp object platforms).  Used
#improperly, you can end up with the "it's a floor wax AND a dessert topping"
#effect...
#
#It all depends on the programmer.

This is the most relevant comment that has been made so far.  Just like
power tools that carpenters use, Multiple Inheritance isn't something to
be used casually.  You really do have to know what you are doing.

I would say that most programmers aren't at the level of expertise in object
programming to know what to do with MI.  I know I'm not there yet.  But
when I reach that level, I know that I want the option to try it out.  The
biggest problem with books on C++ and books on object programming in general,
is that there aren't any clear-cut examples that show the perfect application
of MI.  So it's kind of a solution waiting for a problem.  Just as with 
object programming vs. procedural programming, it's a good idea to use the
right tool for the right job.

By the way, has anyone read Meyer's book on Eiffel?  Eiffel has been touted
(by him and others) as having the cleanest implementation of MI of any language
so far.  I would hope somebody is working on an implementation for the
Macintosh.

-------------------------------------------------------------------------------
-  Patrick Beard, Macintosh Programmer                        (beard@lbl.gov) -
-  Berkeley Systems, Inc.  ".......<dead air>.......Good day!" - Paul Harvey  -
-------------------------------------------------------------------------------

mnykanen@cc.helsinki.fi (07/09/90)

In article <1990Jul5.223032.14604@efi.com>, tim@efi.com (Tim Maroney) writes:
> Object programming is another step towards more human conceptualization
> of tasks.  The whole notion of class inheritance is based on the human
> division of phenomena into categories and subcategories.  Because of
Are you saying that hierarchicality is a fundamental property of human
thought? I think we western 'scientists' have just been educated in the
Aristotelian tradition (although A. himself would have stuck with single
inheritance.. :-) ). This is what you get when making philo/psychological
commitments based on programming practise; conceptually OOP is a mess.
-- 
Matti Nyk{nen
CS Student at Helsinki U, Finland
email: mnykanen@cc.helsinki.FI

The best opinions available; get them while they're hot!

jimm@amiga.UUCP (Jim Mackraz) (07/10/90)

(Rick Holzgrafe) writes:
)Well, I like source too. But one of the best features of OOP is re-usable 
)modules *without* having to hack the source.

Traditionally?  I thought part of Smalltalk was the browsing of class source
code, changing it as needed.

I think it's pretty clear that you can't extend a class by inheritance
in ways that were not anticipated by the author of the class.  If the
"method" hooks you can override aren't in the right places, you are stuck.

I expect that making profound changes in a subclass will often require the
source to the superclass, and almost as often only be feasible if you
can modify that source.

	jimm

-- 
--------------------------------------------------	- opinions by me
"This voice console is a *must*.  I press Execute. 
 `Hello, I know that you've been feeling tired.
  I bring you love and deeper understanding.' "		-lyrics by Kate Bush

amanda@mermaid.intercon.com (Amanda Walker) (07/10/90)

Anyone who is doing much work with MPW C++ should probably try to scrape
up a copy of the "Unofficial C++ Style Guide" that David Goldsmith wrote
up.  I know that there's a copy on "A Disc Called Wanda," but I don't know
if it's available in some other fashion for people without CD-ROM players.
It's aimed primarily at people new to C++, but it's got a number of very
useful guidelines, including stuff about keeping multiple inheritance from
producing spaghetti code.

--
Amanda Walker <amanda@intercon.com>
InterCon Systems Corporation

rmh@apple.com (Rick Holzgrafe) (07/12/90)

In article <5991@amiga.UUCP> jimm@amiga.UUCP (Jim Mackraz) writes:
> (Rick Holzgrafe) writes:
> )Well, I like source too. But one of the best features of OOP is 
re-usable 
> )modules *without* having to hack the source.
> 
> Traditionally?  I thought part of Smalltalk was the browsing of class 
source
> code, changing it as needed.
> 
> I think it's pretty clear that you can't extend a class by inheritance
> in ways that were not anticipated by the author of the class.  If the
> "method" hooks you can override aren't in the right places, you are 
stuck.

You're right, and it's why I said "I like source too". It's not easy to 
write a class so that all reasonable extensions can easily be made by 
subclassing. (I know; I've tried.)

But that's the *goal* of OOP (well, one of them anyway :-). Easily 
sub-classable classes increase the productivity of the developers who use 
them.

Try hard to write classes whose users won't need source. Then give them 
source anyway.

==========================================================================
Rick Holzgrafe              |    {sun,voder,nsc,mtxinu,dual}!apple!rmh
Software Engineer           | AppleLink HOLZGRAFE1          rmh@apple.com
Apple Computer, Inc.        |  "All opinions expressed are mine, and do
20525 Mariani Ave. MS: 77-A |    not necessarily represent those of my
Cupertino, CA 95014         |        employer, Apple Computer Inc."

lsr@Apple.COM (Larry Rosenstein) (07/12/90)

In article <5991@amiga.UUCP> jimm@superman.UUCP (Jim Mackraz) writes:
>
>Traditionally?  I thought part of Smalltalk was the browsing of class source
>code, changing it as needed.

That's the way Smalltalk has been traditionally, but even then some parts
aren't available in source form.  (I think that the number of such things in
Smalltalk/V is even larger; for example their compiler.)

>I think it's pretty clear that you can't extend a class by inheritance
>in ways that were not anticipated by the author of the class.  If the
>"method" hooks you can override aren't in the right places, you are stuck.

Then the class wasn't designed properly.  In a well-designed class, each
method does only 1 function, so it is easy override the function you need to
change.  On the other hand, if a method does 2 things and you need to
override only one of them, then you have to re-implement something you
shouldn't need to.

>I expect that making profound changes in a subclass will often require the
>source to the superclass, and almost as often only be feasible if you
>can modify that source.

I'm sure that you can always do this such that the class won't serve your
needs.  But in that case, you are outside the design center of the class.
It's the same as extending any tool beyond its intended use.  The challenge
in designing a class is to make its applicability as broad as possible.

There are class libraries on the market that ship in object code-only form.
(The same as there are subroutine libraries that ship in object form.)  It
should be possible to find out whether source is a requirement for a class
library. 

-- 
		 Larry Rosenstein,  Object Specialist
 Apple Computer, Inc.  20525 Mariani Ave, MS 46-B  Cupertino, CA 95014
	    AppleLink:Rosenstein1    domain:lsr@Apple.COM
		UUCP:{sun,voder,nsc,decwrl}!apple!lsr

lsr@Apple.COM (Larry Rosenstein) (07/12/90)

In article <2699F590.3593@intercon.com> amanda@mermaid.intercon.com (Amanda Walker) writes:
>Anyone who is doing much work with MPW C++ should probably try to scrape
>up a copy of the "Unofficial C++ Style Guide" that David Goldsmith wrote
>up.  I know that there's a copy on "A Disc Called Wanda," but I don't know

It's in develop #2.

-- 
		 Larry Rosenstein,  Object Specialist
 Apple Computer, Inc.  20525 Mariani Ave, MS 46-B  Cupertino, CA 95014
	    AppleLink:Rosenstein1    domain:lsr@Apple.COM
		UUCP:{sun,voder,nsc,decwrl}!apple!lsr

casseres@apple.com (David Casseres) (07/13/90)

In article <9093@goofy.Apple.COM> rmh@apple.com (Rick Holzgrafe) writes:
> Try hard to write classes whose users won't need source. Then give them 
> source anyway.

Since I made the remark that started this sub-thread, I should add that I 
heartily agree with the above.  Let me try a better way of saying what I 
was getting at in the first place:  I would rather be grubbing around and 
rewriting source code to figure out how to make a poorly designed class do 
what I want, than putting together a pot of spaghetti made out of poorly 
designed classes and multiple inheritance.  Obviously, it is best if we 
don't have any poorly designed classes to deal with, but life is not 
really like that.

Even with well-designed classes there is *sometimes* a situation where you 
want a new Class X to be able to do things like both Class A and Class B.  
My preferred way of dealing with this is to let X be a subclass of A and 
let each instance of X contain an instance of B.  In some sense this is 
not as elegant as multiple inheritance, but in another sense it is more 
elegant: it encapsulates the problem much more effectively -- X and its 
subclasses need not worry about which of their parents they are inheriting 
from.

David Casseres
     Exclaimer:  Hey!

tim@efi.com (Tim Maroney) (07/14/90)

In article <1990Jul2.181147.1672@efi.com> tim@efi.com (Tim Maroney) writes:
>>The people doing the MPW compilers seem to think that multiple
>>inheritance is not important.  It's not possible at all in Object
>>Pascal, and apparently is impossible to use in real (handle-based)
>>applications in C++.  I think this is a cavalier attitude.  I've only
>>been using Object Pascal for a couple of months now, and my only
>>earlier OOP experience was with a flavored dialect of Franz Lisp many
>>years ago; but I have already encountered a number of cases where the
>>lack of multiple inheritance imposes inelegant solutions.  The
>>"seaplane" analogy seems to be a frivolous way of dismissing this
>>important technique.

In article <9007@goofy.Apple.COM> shebanow@Apple.COM (Andrew Shebanow) writes:
>Although it might seem hard to believe given the inflammatory tone
>of Tim's missive, there are many people here at Apple who think
>that MI is important.

What I find hard to believe is that anyone would seriously call the
above "inflammatory".  There seems to be an attitude that any criticism
of Apple technical policy is inherently inflammatory, even if its
language is moderate and its arguments carefully drawn.  Is it really
"inflammatory" to call an attitude "cavalier" and an argument
"frivolous"?  If so, how would it be possible to make any criticism
that was not "inflammatory"?

>The limitations on the use of MI in handle based objects are caused
>by C++'s object model, and not by a lack of concern on the part
>of Apple's engineers. If anyone can figure out a good way to solve
>this problem without rewriting all of CFront, we would of course be
>very interested in hearing about it.

A number of small developers have come out with native C++ compilers
for DOS, I believe.  I doubt that writing a compiler would be a serious
strain on Apple's bountiful development resources.  cfront is a slow
interim solution, which you'll have to break with sooner or later.

However, I don't know that the best way to solve the problem involves
handle+offset ways of accessing objects, as suggested by a few people
here.  Suppose that an object begins with a class offset table,
consisting of an array of pairs (class id, offset to members).  Then
the generated code uses a double-offset operation to get to the members
of the class it's dealing with.  There is a small performance penalty,
but it keeps the model fairly clean, and you only have to do the table
lookup once per object per method.

>Object Pascal doesn't support MI primarily for historical reasons.
>The language wasn't designed with MI in mind, and adding MI
>to it would be a decidedly non-trivial change. However, Apple's
>Advanced Technology Group is looking at doing an updated
>version of the Object Pascal language - for more information,
>see the last issue of the MacApp Developer's Association publication,
>Frameworks".

Perhaps we should subscribe to it.  Object Pascal has two major
deficiencies.  One is the lack of multiple inheritance; the other is
the lack of information hiding (private methods and members).  Is the
ATG also looking at adding information hiding?

tim@efi.com (Tim Maroney) (07/14/90)

In article <1990Jul5.223032.14604@efi.com> tim@efi.com (Tim Maroney) writes:
>>A loop construct is
>>closer to the ordinary human way of seeing tasks than is a GOTO.  If
>>we're telling soemone how to do something, we might say "do this ten
>>times" or "keep doing it until the film is dry" or something of that
>>kind; we are much less likely to say "go back to step 5".

In article <1990Jul6.182948.12005@ux1.cso.uiuc.edu> dorner@pequod.cso.uiuc.edu
(Steve Dorner) writes:
>As long as we're waxing philosophical:
>
>I think I'm far more likely to tell someone, "if the film isn't dry,
>do it again."  And "start over from the beginning" is also very common.
>Both of these are very much GOTO's.

Not at all!  They are very much loop instructions, and very much *not*
GOTO's.  Each of them carries semantic information informing the person
that this is an instruction to repeat something.  I suggest re-reading
the above in this light.  "Go to step 5" carries no such semantic
information.  It is merely notational, devoid of inherent meaning.

>I think loops and such are in fact very UNnatural. They take quite a bit
>of getting used to, which is not a comment on their utility or elegance.
>The same may be said of OOPL's; they're darn weird at first.

I used to help quite a few people who were learning to program at my
university.  I really don't remember any of them having much trouble
internalizing the concept of a loop, though some did have problems with
some of the subtleties of particular programming language's
*implementation* of loops -- particularly in Fortran and C.

tim@efi.com (Tim Maroney) (07/14/90)

In article <1990Jul5.223032.14604@efi.com>, tim@efi.com (Tim Maroney) writes:
>> Object programming is another step towards more human conceptualization
>> of tasks.  The whole notion of class inheritance is based on the human
>> division of phenomena into categories and subcategories.  Because of

In article <2742.26985429@cc.helsinki.fi> mnykanen@cc.helsinki.fi writes:
>Are you saying that hierarchicality is a fundamental property of human
>thought?

Yes.  Description inherently operates at various levels of
abstraction.  There are animals; there are dogs; there is my dog.
If you know of languages or cultures which do not operate in this
hierarchical fashion, I would like to hear about them (always
interested in new ways of thinking!)

>I think we western 'scientists' have just been educated in the
>Aristotelian tradition (although A. himself would have stuck with single
>inheritance.. :-) ).

I can't claim to be a cultural anthropologist, but levels of
abstraction in decription certainly precede Aristotle, and appear in
cultures which were not influenced by Aristotle.  Look at, say, the
Trobriand Islanders' mythology.  They have concepts both for particular
animals, and for animals overall, and for types of animals; for people,
for people of different genders, and for individual people; for
spirits in general, for families of spirits, and for particular spirits.

If you were doing a simulation of these concepts in an object language,
you would represent them with superclass and subclass relationships.

>This is what you get when making philo/psychological
>commitments based on programming practise; conceptually OOP is a mess.

Conceptually, our minds are a mess.  Look at the syntax of natural
language if you want to see a real mess.  The question with a
programming language is how close its mess approximates to our
ordinary mess....

shebanow@Apple.COM (Andrew Shebanow) (07/17/90)

>What I find hard to believe is that anyone would seriously call the
>above "inflammatory".  There seems to be an attitude that any criticism
>of Apple technical policy is inherently inflammatory, even if its
>language is moderate and its arguments carefully drawn.  Is it really
>"inflammatory" to call an attitude "cavalier" and an argument
>"frivolous"?  If so, how would it be possible to make any criticism
>that was not "inflammatory"?

It isn't imflammatory to criticize Apple. There are plenty of people
on the nets who criticize Apple all the time, and nobody bats an eye.
Criticizing Apple for not supporting MI on handle based objects is
fine - but jumping to the conclusion that this is a "cavalier" attitude,
and then trumpeting that conclusion as fact is, IMHO, imflammatory. Your
use of loaded words like "cavalier" and "frivoulous" is also likely
to raise the hackles of the Apple engineers who don't like having
their design decisions, which are often the result of weeks or
months of work, characterized as such by someone who has little or
no idea of the issues involved.

>Perhaps we should subscribe to it.  Object Pascal has two major
>deficiencies.  One is the lack of multiple inheritance; the other is
>the lack of information hiding (private methods and members).  Is the
>ATG also looking at adding information hiding?

Yes, ATG is looking at those issues as well. The basic goal is to
make Object Pascal support an equivalent set of OOP features as C++,
while preserving the spirit of Object Pascal.

I would recommend Frameworks to anyone who is interested in
OOP on the Mac.

Have fun,

Andrew Shebanow