Favour composition over inheritance ( and III )
But there are more heavy weight reasons to favour composition over inheritance.
First, inheritance doesn’t allow to change the implementations of the subclasses at run time, and breaks encapsulation, because the implementation of the superclass is visible through the subclasses.
However, composition is usually made at run time, so all objects must have a good knowledge of the other objects’ interfaces ( and only of the interfaces ), which favours encapsulation.
But there’s also another advantage in composition. If we rely more on composition that on inheritance, our programs will be more like a puzzle made of a lot of different pieces, each one responsible of a little task. So, our class hierarchy won’t be a huge dinosaur, hardly flexible, and hard to maintain. But also, the application behaviour will change easily at run time, and won’t be constrained by the code we’ve written in a class.
We’ll try to illustrate this with another example. Suppose we are working on an application for a football ( or soccer ) club. One of the modules of this application must show a list of the club’s members, that is loaded form a XML file.
We can implement a class that extends XML, and that loads and parses the file, and returns an array of objects, each one containing the data of one of the club’s members.
What if the rest of the program changes, and now we won’t need an array of objects, but another data structure?. Well, we could write another class, that also extends XML, but with a different parser.
But we could have also solved our problem follwing the puzzle example. We could develop a class that loads the XML file, and returns an XMLNode containing the XML firstChild, and delegate the responsibility of parsing and building a data structure to the class that is going to need and use those data. Why?. Because, if we do everything in a unique class, that class will need to know about the data, and the ussage of that data by the rest of the program. But if we separate the responsibilities, everything will be more flexible, and we also have a component ( a class that loads a XML and return a XMLNode ) that can be used in all our projects. And we also decouple the data from the service to obtain it, of course.
So, it seems that composition is the perfect solution for everything. Well, not everything. There are also some points about composition that must be considered. First of all, we said that building our systems using little piezes favours flexibility, but it also makes our program more difficult to debug. And also, the performance of the code based on composition is a bit slower than the performance of the code based on inheritance ( which can be very important in Flash ).
In fact, we should use both techniques mixed. For instance, back to the example of the XML, both the class that loads the XML file could ( in fact, should ) extend XML The class that parses the data should extend an abstract class ( or implement an interface ) with the parser method.
Inheritance is not evil, at least when be use it to solve our problems, not as a "design imposition". But, in general, our problems can be easier to solve if we favour composition over inheritance. Don't you agree?
Comentarios
Thank you for your insight, you have really brought up several good points. Ill definately have to come back when I can spend more time on the idea.
Publicado por: Ryan Guill | November 8, 2004 05:00 AM
I favour composition more so these days then inheritance, mainly because i've been burnt by inheritance and ended up backing myself into a corner (probably due to under-experience).
I will say this though, Composition is confusing to someone who hasn't either read your API's docs or understood your code. Sometimes the "Mix-in" can confuse composition aswell, in that you have a "has-a" relation ship with an object that can also bolt on some functionality to your actual object, which in turn also can be confusing aswell (debug also).
But really good posts - I still consider myself a newbie to OO/P but its articles like this that kind of help steer me in the right direction.
Publicado por: Scott Barnes | November 8, 2004 05:15 AM
We use inheritance, if we have objects, that are very similar in their functionality (eg. father and son).
We use composition, if we have objects, that are not similar but nevertheless relate to each other (eg. father and his car).
These two concepts are describing totally different tasks and therefore are not comparable in terms of one being better or not.
So i'm not preferring one or the other. Instead, i'm using each one right then, when it makes sense.
Publicado por: Sven Busse | November 8, 2004 09:55 AM
Sven, I wish things were so cut and dried in th real world of programming. It's easy to say "a worker is a human being", but I find such pseudo examples kind of useless. Personally, I've never coded a HumanBeing class. In the real world of interface and application development, there are always several different ways of looking at things, and it often takes a few iterations to come up with a good structure. Maybe you've been doing this for a million years and can see design patterns in your sleep. But for most of us human beings / developers, there will be plenty of points where we have to choose between inheritance and composition. The intro chapters of GoF go into this very same discussion in depth as well.
Publicado por: Keith Peters | November 8, 2004 12:02 PM
Sven, if your development process is always so cut and dried, I really envy you. I think most of us normal HumanBeing/Developers go through a few iterations before coming up with the final model for an application, and there are always several points where the decision of inheritance/composition can be made.
Publicado por: Keith Peters | November 8, 2004 03:38 PM
Nice to see people talking about this.....
Really it comes down to the old "isA"/"hasA" relationship, and many developers are just being lazy by using the "isA" (inheritance) relationship simply for convenience of less coding....
Both relationships have relevance within a structured OOP application, one should not be "favoured" over another, the choice should be based on which is most suited to the scenario.
Publicado por: keith | November 8, 2004 03:54 PM
I don't think it's a case of favouring composition over inheritance, or the other way around. You just use the approach which is most usefull given a certain scenario.
I most of the time I use composition because I want to pick different kinds of functionailty from different sources. But once there's a confined set of shared functionality, I'll use inheritance as well. No big deal, whatever makes it work best right :).
Publicado por: Bob Donderwinkel | November 8, 2004 07:37 PM
This was an interesting article series (though apparently somewhat controversial :)!
The same thoughts are echoed in Moock's "Essential ActionScript 2.0" (pg 208), and even more closely at http://www.artima.com/designtechniques/compoinh.html
Publicado por: Ville Walveranta | December 9, 2004 05:43 AM