dan-hankins@cup.portal.com (Daniel B Hankins) (10/29/88)
An addendum to my previous posting: In the case where one wishes to inherit everything from a parent save a few individual message handlers or local variables, one might want something like: class X; superclasses A, B, C; from A discard Y; . . . This would allow even more flexibility in inheritance. Another alternative is to handle name importing the way Modula-2 does - if an individual name is wanted, one specifies from X inherit Y but if complete inheritance is wanted, inherit X is used, and references to names in X must be prefixed with their class name, as in: tell X.K move-arm Any ideas or suggestions? Dan Hankins
dan-hankins@cup.portal.com (Daniel B Hankins) (11/13/88)
Thanks for all the email responses to my query. To summarize: Multiple inheritance is an indication that something is wrong with the class hierarchy. Restructure that and single inheritance should do fine. This also does away with things like the specific inheritance mechanism and method/variable drop clauses. Lexical scoping inhibits reusability. Solution: allow multiple classes with the same name, and distinguish them on the basis of what their superclass chain is. Since this language has no declaration of variable class (all type checking is done by something like lint, and at runtime), this won't create problems with the user having to type in unmanageably long names in type declaration statements. Dan Hankins
steve@ragman (Steve Stevenson) (11/14/88)
From article <11256@cup.portal.com>, by dan-hankins@cup.portal.com (Daniel B Hankins): > Thanks for all the email responses to my query. To summarize: > > Multiple inheritance is an indication that something is wrong with the class > hierarchy. > > Lexical scoping inhibits reusability. I think these are the same problem. The insistance on a hierarchy may put you in a bind both performance wise and logically. Recall the problems with type theory in general. Another problem is that a hierarchy of true ABSTRACT data types ( in the sense that a queue apart from any implementation ) is not tantamount to a package or module.
ech@poseidon.ATT.COM (Edward C Horvath) (11/15/88)
From article <11256@cup.portal.com>, by dan-hankins@cup.portal.com (Daniel B Hankins): > Thanks for all the email responses to my query. To summarize: > Multiple inheritance is an indication that something is wrong with the class > hierarchy. Restructure that and single inheritance should do fine... I used to think so, too. Then I read Meyer's book: multiple inheritance is a concept with immense power, not a "hack." I am less convinced of the need for REPEATED inheritance, i.e. inheriting from two or more classes with a common ancestor. Even here, however, notions like nodes which are simultaneously on two types of linked lists are well-served by repeated-inheritance-with-renaming. =Ned Horvath=
sommar@enea.se (Erland Sommarskog) (11/18/88)
Daniel B Hankins (dan-hankins@cup.portal.com) writes: >Thanks for all the email responses to my query. To summarize: > >Multiple inheritance is an indication that something is wrong with the class >hierarchy. Restructure that and single inheritance should do fine. Could anyone elaborate this? I fail to see what is bad with multiple inheritance. If I want to store an object in a tree and a linked list simultaneously, what is wrong with my class structure? -- Erland Sommarskog ENEA Data, Stockholm sommar@enea.se A radio station is a four-letter word.
dan-hankins@cup.portal.com (Daniel B Hankins) (11/20/88)
In article <795@euraiv1.UUCP> reino@euraiv1.UUCP (Reino de Boer) writes: >How about having two separate classes for a linked list: >Class List >Class EmptyList >and trying to build a stack as subclass of List and EmptyList. Isn't >multiple inheritance nicer than trying to make class List act like two >separate concepts ? I suggest trying to pick a better example. It seems to me that if you are going to have two separate classes for a linked list, you might as well have two separate classes for a stack. In this case, those classes would be Stack and EmptyStack, which would be subclasses of List and EmptyList, respectively. In article <578@poseidon.ATT.COM> ech@poseidon.ATT.COM (Edward C Horvath) writes: >> Multiple inheritance is an indication that something is wrong with the class >> hierarchy. Restructure that and single inheritance should do fine... > >I used to think so, too. Then I read Meyer's book: multiple inheritance >is a concept with immense power, not a "hack." > >I am less convinced of the need for REPEATED inheritance, i.e. inheriting >from two or more classes with a common ancestor. Even here, however, >notions like nodes which are simultaneously on two types of linked >lists are well-served by repeated-inheritance-with-renaming. In article <4086@enea.se> sommar@enea.se (Erland Sommarskog) writes: >>Multiple inheritance is an indication that something is wrong with the class >>hierarchy. Restructure that and single inheritance should do fine. > >Could anyone elaborate this? I fail to see what is bad with multiple >inheritance. If I want to store an object in a tree and a >linked list simultaneously, what is wrong with my class structure? These two sound like the same example. In either case, is is much better programming practice to have a class Node which is not tied to any structure. Objects which are nodes of class TreeNode or ListNode or whatever should have objects of class Node as an acquaintance (or variable, in Smalltalk terminology). In article <678@quintus.UUCP> pds@quintus.uucp (Peter Schachte) writes: >A better example is toy truck. A toy truck IS a toy and it IS a truck, >so it might make sense to have it inherit from both. It could inherit >number-of-wheels from truck, and qualitative-size from toy. But >dealing with the conflicts, it seems to me, is nontrivial at best, and >sometimes a quagmire of hacks. > >Does someone have a GOOD theory of multiple inheritance that deals with >conflicts in more than an ad hoc way? This is the tricky one. This is the one that makes me think that perhaps a tree, or even a digraph, is not the proper way to think about classifying objects. What is the proper way? I'll let you know when and if I figure it out. Dan Hankins
halvers@phecda.steinmetz (Pete Halverson) (11/21/88)
From my experience, multiple inheritence seems to be most useful when you're trying to represent characteristics that are somehow orthogonal, i.e. land vehicles vs. sea vehicles, motorized vs. non-motorized, military vs. commercial. Single-inheritance-only schemes require you to define a separate class for each combination (i.e. Motorized-Military-LandVehicle, NonMotorized-Commercial-SeaVehicle). If you have many dimensions and many subclasses, the resulting cross-product is going to get real nasty, real fast. Not to say these kinds of systems aren't complex (I'm currently in the midst of trying to decipher the Symbolics window class structure) but multiple inheritance can at least directly represent these orthogonalities.
frode@m2cs.naggum.se (Frode Odegard) (11/21/88)
In article <4086@enea.se>, sommar@enea.se (Erland Sommarskog) writes: > > I fail to see what is bad with multiple inheritance. If I want to > store an object in a tree and a linked list simultaneously, what is > wrong with my class structure? > > -- > Erland Sommarskog > ENEA Data, Stockholm > sommar@enea.se > A radio station is a four-letter word. Some people are worried about the dependency problems and structure implications of allowing multiple inheritance. To my knowledge, Eiffel is the only commercial system which supports multiple inheritance [except LISP-based systems?] and it will be interesting to see if the reactions will continue to be so positive as they've claimed them to be so far.. The company I work for is developing an advanced Modula-2 environment where a lot of the effort in supporting large-scale projects (i.e. multi-site, 200,000+ loc etc..) has gone into designing formal notations for defining architecture and dependency demands which go beyond the scope of the Modula-2 itself. I guess the conclusion we've reached is that it is easier to solve structural problems (like dependency management) when the language is simple, rather than have a HUGE language for which it is difficult to build an equally powerful environment [look at Ada: only Rational has been able to come up with a decent environment, and that's 2 million lines of Ada code, they claim]. The OOP fever has many similarities to the RISC fever. People seem to think that as long as something is O-O it is good. This is simply not true. Using notations which support refinement and extension of previously written software components is going to help you in terms of productivity, but you're still going to get maintenance problems and in an environment like Smalltalk, you just don't go in and fiddle too much with class dependencies :-) National Semiconductor (which hasn't announced any RISC processor yet) has stated that "RISC is a technology - not a product". Perhaps it is time to be more rational about OOP, too. OOP is a new approach to problem-solving, it's exciting, but it's not the only way of getting good results. Sometimes it can be worth the trouble to mix O-O approaches with others. Our Modula-2 environment, for example, is based around a distributed object-oriented database, but we didn't create an O-O database *programming* language. There's a new notation for declaring database classes, but the methods are implemented in standard Modula-2. Sigh..I know...I know...not of all this deals with multiple inheritance, but I got kinda carried away. See U all on the bit-stream! - Frode
akwright@watdragon.waterloo.edu (Andrew K. Wright) (11/21/88)
In article <11522@cup.portal.com> dan-hankins@cup.portal.com (Daniel B Hankins) writes: >This is the tricky one. This is the one that makes me think that perhaps >a tree, or even a digraph, is not the proper way to think about classifying >objects. > >What is the proper way? I'll let you know when and if I figure it out. The real world is full of all kinds of arbitrary relationships. If you want to directly model the real world, you will have to allow arbitrary relations in your language, ie. an arbitrary graph. The object oriented approach seems to be "the real world is too complicated; lets fix it (force it into a tree) and then model it". This works fine when the problem you are trying to model fits your inheritance tree naturally, but when the fit is unnatural, you have given the programmer some more work. An approach which seems to offer more promise of modelling the real world directly is parametric polymorphism. Algorithms rather than objects specify what other algorithms they require to operate. Universal and existential quantifiers can be used in the type specification of algorithms to make algorithms more reusable. For example, here is the type specification for "sort", which can sort arrays of any type: sort: [ forall t: type, forall i: int, forall j: int, exists >: [t,t] bool, a: [i..j] array t ] proc void; This says "sort" operates on arrays of any type and any number of elements, so long as the function ">" is defined between the elements. This is a simplified example; a general sort would not require the data structure to be an array. Sorting linked lists may be equally desirable, and requires sort to be further generalized to require that swap (or := and a temporary constructor) exist. -------- Andrew K. Wright akwright@watmath.waterloo.edu CS Dept., University of Waterloo, Ont., Canada.
sommar@enea.se (Erland Sommarskog) (11/22/88)
Daniel B Hankins (dan-hankins@cup.portal.com) writes: >I said: >>If I want to store an object in a tree and a >>linked list simultaneously, what is wrong with my class structure? > >These two sound like the same example. In either case, is is much better >programming practice to have a class Node which is not tied to any >structure. Objects which are nodes of class TreeNode or ListNode or >whatever should have objects of class Node as an acquaintance (or variable, >in Smalltalk terminology). So If have a link and a tree class just lying around I should just ditch them in favour of a more general node class which I haven't? So much for reuseable software! And I fail to see how I make it with my objects as nodes simply. I want to apply typical list operations as delete/insert them into the list, go to the next element and so. And I want to visit all of them in prefix order, insert them sorted into the right place in the tree, and so on. -- Erland Sommarskog ENEA Data, Stockholm sommar@enea.se "Frequently, unexpected errors are entirely unpredictable" - Digital Equipment
nobody@tekecs.TEK.COM (-for inetd server command) (11/23/88)
In article <12636@steinmetz.ge.com> halverson@crd.ge.com (Pete Halverson) writes: >From my experience, multiple inheritence seems to be most useful when >you're trying to represent characteristics that are somehow orthogonal, >i.e. land vehicles vs. sea vehicles, motorized vs. non-motorized, military >vs. commercial. Single-inheritance-only schemes require you to define a >separate class for each combination (i.e. Motorized-Military-LandVehicle, >NonMotorized-Commercial-SeaVehicle). If you have many dimensions and many >subclasses, the resulting cross-product is going to get real nasty, real >fast. > >Not to say these kinds of systems aren't complex (I'm currently in the >midst of trying to decipher the Symbolics window class structure) but >multiple inheritance can at least directly represent these orthogonalities. I'm not really "for" or "against" multiple inheritance, but I haven't seen anything that shows that multiple inheritance really adds anything. Couldn't you have one vehicle class with 3 instance variables? One instance variable for each of the "dimensions" (e.g. surface: land vs. sea, propulsion: motorized vs. non-motorized, ...). The vehicle class could forward messages to the appropriate instance variable. Some OO languages allow methods to be expanded in line, and can often avoid the extra method lookup, so that the forwarding wouldn't have to incur a run time penalty. Adding, for example, more surfaces for vehicles (e.g. add to land and sea the surfaces air, space, ...) wouldn't have to require changes to the vehicle class. This doesn't seem to have the cross-product effect you were talking about. Or maybe I just didn't understand the problem, Paul Scherf, Tektronix, Box 1000, MS 61-028, Wilsonville, OR, USA paulsc@orca.GWD.Tek.COM tektronix!orca!paulsc
barmar@think.COM (Barry Margolin) (11/24/88)
In article <10660@tekecs.TEK.COM> paulsc@radio_flyer.UUCP (Paul Scherf) writes: >but I haven't seen anything that shows that multiple inheritance >really adds anything. > >Couldn't you have one vehicle class with 3 instance variables? >One instance variable for each of the "dimensions" >(e.g. surface: land vs. sea, propulsion: motorized vs. non-motorized, ...). >The vehicle class could forward messages to the appropriate instance variable. >Some OO languages allow methods to be expanded in line, >and can often avoid the extra method lookup, >so that the forwarding wouldn't have to incur a run time penalty. This has a few problems. One is that each time you think of a new dimension you must modify the vehicle class in order to add a new instance variable to embody that dimension. A more serious problem is that these sub-instances are running with the wrong notion of "self". If they perform an operation on self they will not be operating on the whole vehicle, just their own aspect. "Self" is a very important concept in OO programming, as it allows a method in a component class to perform an operation whose results depend on the actual class of the object. With this workaround for the lack of multiple inheritance, each sub-instance must either have an instance variable holding its parent, or every operation must pass the parent as an argument. But you would also need the grandparent, the great-grandparent, etc. Multiple inheritance automates and generalizes this in an elegant manner. By the way, your suggestion can actually be used as an argument against inheritance in general, since the same mechanism could be used to pass on operations from a class to a single superclass. I believe there are some OO systems that work this way. I don't know how they deal with the "self" issue. Barry Margolin Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar
pds@quintus.uucp (Peter Schachte) (11/24/88)
In article <9861@watdragon.waterloo.edu> akwright@watdragon.waterloo.edu (Andrew K. Wright) writes: ... >This says "sort" operates on arrays of any type and any number of elements, >so long as the function ">" is defined between the elements. > >This is a simplified example; a general sort would not require the >data structure to be an array. Sorting linked lists may be equally >desirable, and requires sort to be further generalized to require >that swap (or := and a temporary constructor) exist. But that's not a good idea, efficiency-wise. You might want to use Quicksort to sort arrays, but you sure wouldn't want to use it for lists. You'd probably use a merge sort. Take it even a step farther. If the type of element you're sorting is small, and comparison is cheap (e.g., sorting integers) you'd want to use quicksort. If the number if distinct keys is small, you might use a radix sort. If the data to be sorted will not fit in memory, maybe you'd use a heapsort to get sorted pieces followed by merge passes. If you're talking about real-world constraints that make single-inheritance systems painful, there are also real world constraints that make a polymorphic system painful, too. Nothing's perfect. -Peter Schachte "Clean water? I'm for clean water." pds@quintus.uucp -George Bush ..!sun!quintus!pds
pds@quintus.uucp (Peter Schachte) (11/24/88)
In article <12636@steinmetz.ge.com> halverson@crd.ge.com (Pete Halverson) writes: >From my experience, multiple inheritence seems to be most useful when >you're trying to represent characteristics that are somehow orthogonal, >i.e. land vehicles vs. sea vehicles, motorized vs. non-motorized, military >vs. commercial. Single-inheritance-only schemes require you to define a >separate class for each combination (i.e. Motorized-Military-LandVehicle, >NonMotorized-Commercial-SeaVehicle). If you have many dimensions and many >subclasses, the resulting cross-product is going to get real nasty, real >fast. In article <10660@tekecs.TEK.COM> paulsc@radio_flyer.UUCP (Paul Scherf) responds: >Couldn't you have one vehicle class with 3 instance variables? >One instance variable for each of the "dimensions" >(e.g. surface: land vs. sea, propulsion: motorized vs. non-motorized, ...). >The vehicle class could forward messages to the appropriate instance variable. >Some OO languages allow methods to be expanded in line, >and can often avoid the extra method lookup, >so that the forwarding wouldn't have to incur a run time penalty. I see two problems with this approach. First, it's a pain to define lots of methods for vehicle that just forward the message to the appropriate instance variable. More seriously, though, the object receiving the message is no longer the one you're really talking about, so self messages go to the wrong place. For example, suppose vehicle has a position message that returns the vehicle's position, and both motorized and non-motorized define a halt method. Further suppose that in one or both cases, halt needs to know the vehicle's position. The obvious way to do this is to send a position message to self. But this won't work, because self is motorized or non-motorized, rather than the vehicle. Well, you can patch around this by having a back-pointer from motorize and non-motorized to the vehicle, and having methods for all of vehicle's messages that forward to the vehicle. That of course means that you have to have a separate motorized object for every motorized vehicle you create. It starts getting ugly. I think a similar approach could work quite well, though, if it were built into the OO system. It would have to understand attributes, like propulsion in the above example. An attribute would be like a class, except that they can't be instantiated, and a class can specify that certain attributes must be specified when it is instantiated. So vehicle would be a class that requires propulsion, which would be an attribute (sort of like a mixin, for flavors people). An attribute specification would include a set of methods that its instances (this is probably a bad choice of word -- in this case I mean motorized and non-motorized) must supply. When an instance of vehicle it gets all the methods from the vehicle class, plus the methods from the chosen attribute. But it's still a single object. I hope I'm being at least faintly clear. -Peter Schachte pds@quintus.uucp ..!sun!quintus!pds
dan-hankins@cup.portal.com (Daniel B Hankins) (12/04/88)
In article <737@quintus.UUCP> pds@quintus.uucp (Peter Schachte) writes: >I think a similar approach could work quite well, though, if it were >built into the OO system. It would have to understand attributes, like >propulsion in the above example. An attribute would be like a class, >except that they can't be instantiated, and a class can specify that >certain attributes must be specified when it is instantiated. So vehicle >would be a class that requires propulsion, which would be an attribute >(sort of like a mixin, for flavors people). An attribute specification >would include a set of methods that its instances (this is probably a >bad choice of word -- in this case I mean motorized and non-motorized) >must supply. When an instance of vehicle it gets all the methods from the >vehicle class, plus the methods from the chosen attribute. But it's >still a single object. > >I hope I'm being at least faintly clear. I had to think about this one for a while. For a while I thought it was the same as multiple inheritance. But I can see that it has potential for a more natural expression of an object description. Objects are like nouns, messages/methods are like verbs, and attributes are like adjectives and adverbs. However, your description is a little confusing. Could you possibly append an example of a class definition using attributes, and an example of an attribute definition? Also, how do you get attributes to work together? How do you get them to agree on variable names which are meant to be shared, such as for example vehicle position? Dan Hankins