Path: utzoo!utgpu!news-server.csri.toronto.edu!clyde.concordia.ca!uunet!bu.edu!snorkelwacker!apple!lsr From: lsr@Apple.COM (Larry Rosenstein) Newsgroups: comp.sys.mac.programmer Subject: Re: Multiple Inheritance -- Is It A Luxury? Message-ID: <9036@goofy.Apple.COM> Date: 7 Jul 90 01:49:16 GMT References: <15132@reed.UUCP> <268BA8DC.4CD4@intercon.com> <8937@goofy.Apple.COM> <268C032E.5137@intercon.com> <1990Jul2.181147.1672@efi.com> Organization: Apple Computer, Inc. Lines: 83 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