Path: utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!uunet!mcsun!inesc!unl!news From: px@fctunl.rccn.pt (Joaquim Baptista (pxQuim)) Newsgroups: comp.lang.c++ Subject: Re: Inheritance vs. Composition Message-ID: Date: 16 Feb 90 00:33:53 GMT References: Sender: news@fctunl.rccn.pt (USENET News System) Followup-To: comp.lang.c++ Organization: Universidade Nova de Lisboa -- Lisbon, Portugal Lines: 166 In-reply-to: gza@mentor.cc.purdue.edu's message of 13 Feb 90 07:55:37 GMT In article gza@mentor.cc.purdue.edu (William R Burdick) writes: The difference between inheritance (or generalization) and composition (or aggregation) is a tough point to figure out without some good examples (I hope I can give some here). Depending on what language you use and what you use your objects for, you may not be able to tell what the difference is right off. Mainly, inheritance passes on behavior to subclasses and composition passes on form to aggregations. As an easy way to tell the difference right off (using multiple inheritance), consider readable files, writable files, and read-write files. You can say that a read-write file inherits behavior from readable files and writable files. If you were to try to make a read-write file out of a composition, you might end up with an object containing two files, a readable file and a writable file. If you make a Read-Write File (the class) a subclass of Read File and Write File, you get a kind of file which can be read from and written to. classes use inheritance and classes are definitions of objects. Instances use composition, and instances are the objects. A particular read-write file does not inherit behavior from its superclass because it is not a class, it is a file, while a read-write file could be composed of a read file and a write file. In article gza@mentor.cc.purdue.edu (William R Burdick) writes: We often talk about reuse, but we must distinguish between (at least) two different forms of reuse: reuse of code and reuse of abstraction. The "American" argument for OOP is to reuse existing code, while the "European" argument is to use inheritance as a structuring and abstraction mechanism. I find both equally important, but reuse of code is much easier than reuse of abstraction. While I was reading this I could not stop myself from wandering about delegation, one of the mechanisms proposed in the Actor model. I could profit from some cleaning up of the "name space" that includes Inheritance, Composition and Delegation. *** Inheritance Whatever inheritance is used for, I guess we all agree on what it is. It is a mechanism by which you say that a "thing" (object, class, or whatever) is made from another "thing", by changing some functionality (or declarativity, or whatever). This is, of course, a form of "reuse of code" or "reuse of abstraction", whatever the programmer or designer has in mind. *** Composition Composition, on the other hand, seems to have been described as building a "thing" which uses other "things". In a Smalltalk way, It would be like having an object with two other objects as instance variables. I think this last definition should be broken in two different things. On the first case, the functionality (or interface, or whatever) or the compose "thing" is very similar to the functionality of the "things" it is made of. A good example would be the relation between a read-write "thing" and the corresponding read and write "things". This is a case where I think that some kind of multiple inheritance is appropriate. Multiple inheritance with some kind of "merging" of common instance variables and some kind of selecting or overwriting of the common methods would probably do the trick. The other case of composition arises when the functionality of the new object is quite different from the functionality of its components. For instance, suppose I have some read "thing" that allows me to read characters, and that I want to build another one that reads tokens. The token reader "thing" will probably "own" a character reader "thing", but I find it difficult to mantain that the new object is "composed" from the previous one. In this case, I think I am just reusing abstractions, ie, I built an abstract token reader from an abstract character reader. So, either I am missing something, or the word "composition" seems empty of content to me. But... *** Delegation The word "delegation" means to me the following: when asked to do something, an object will instead ask another object to do the same thing. The Actor model seems to use this concept to model continuations (I'm not sure though, I was never able neither had the need to fully understand their model). So, we could think that delegation is a word to be used by the Actor model alone. But my concept of delegation has been very helpful in Contextual Logic Programming (aka CxLP; see reference). CxLP just provides a basic notion of unit (sort of model with global parameters) and it is very useful to delegate some of the tasks of a unit to another one. This is often the case when you are programming a layered structure. *** Proposal So, to get this posting to an end, I propose the following "standard cases of object programming": * Single Inheritance: to be used when one "thing" can be described by adding some (usually small) changes to an other one. * Abstraction Reuse: to be used when some "thing" just needs the functionality of another one to get some work done. * Delegation: a special case of Abstraction reuse in which part of the functionality of a "thing" is just the functionality of another "thing". I did left Multiple Inheritance out, for I think it has problems when one tries to inherit the same functionality from several "things" at the same time. The problem is NOT that it can't be solved, but rather that each person will want it solved in the way that best fits the problem they have at hand. I don't like the "throw everything in" solution, so I just left it out. I also left the Code Reuse thing out. One can always use inheritance for Code Reuse instead of Abstraction Reuse, although you will probably end up with some very strange designs. One can also define some "thing" called Reusable_Code_Not_Otherwise_Related... and reuse it. *** References This is the standard paper on Contextual Logic Programming. %A Luis Monteiro %A Antonio Porto %P 284-299 %B Logic Programming: Proc. of the 6th International Conference %S MIT Press series in logic programming %E Giorgio Levi and Maurizio Martelli %C Lisboa %D 19-23 June 1989 %G ISBN 0-262-62065-0 %K =CxLP %X The notion of contextual logic programming is proposed as an extension to the logic programming paradigm. It is tied to the development of a structuring theory for logic programming in which modules, called here units, are sets of context-dependent predicate definitions, and the proof of a certain kind of formulae, called extension form