Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Whether an object physically exists or not, we can choose to model it in different ways. We could arbitarily use generalisation or composition in many cases. However, the GoF principle of "favour composition over generalisation [sic]" guides us to use composition. So, when we model, for example, a line then we create a class that contains two members PointA and PointB of the type Point (composition) instead of extending Point (generalisation). This is just a simplified example of how we can arbitarily choose composition or inheritance to model, despite that objects are usually much more complex.

How do we know that this is the right choice? It matters at least because there could be a ton of refactoring to do if it is wrong?

share|improve this question
9  
Your example doesn't really work because you can't say a line is a point, and therefore it fails the Liskov Substitution Principle and inheritance is not appropriate. –  Dean Harding Apr 10 '11 at 16:56
    
@Dean: As you are probably aware, the example is not central to point. For the record, a line can be represented as an equation defined through two points. –  Carnotaurus Apr 10 '11 at 17:40
    
1  
@Songo: It seems that you have totally missed the point. –  Carnotaurus Sep 15 '12 at 7:59
    
Isn't extending specialization instead of generalization ? –  user61852 Oct 26 '12 at 14:10
show 1 more comment

5 Answers

up vote 17 down vote accepted

It's not always the right choice. It is the favourable one in most cases. When a composite model requires change or extension, it is considerably more resistant to that because you can change the composition without fear of affecting other classes inadvertently.

How do we know this? From experience, and the experience of others.

I have seen many situations where a massive class hierarchy has grown out of what started as a simple concept, and this is where your major refactoring becomes necessary. Meanwhile I have never seen a situation where a composition structure needed refactoring into inheritance.

But my anecdotal evidence should not be enough. Just look around the internet and a good number of people have had the same experiences.

share|improve this answer
    
I'm liking it; take an upvote. –  Carnotaurus Apr 10 '11 at 12:39
    
+1 for "I have never seen a situation where a composition structure needed refactoring into inheritance." –  Kazark Nov 26 '12 at 17:34
add comment

I don't see how composition and generalization are alternatives and failed to find the quote.
Composition and inheritance are (to achieve specialization), and it can be argued, that abstraction and generalization are (to achieve modularity).

What you want is your design to be simple and plausible, which are two qualities that inherently quite easily measured.
In your case, it seems more plausible to compose a line of two points instead of extending it, because you would naturally define a line by two points, rather than by extending the concept of a point.

share|improve this answer
    
Is it more natural? A line is no more two points than it is a single point extended? –  Carnotaurus Apr 10 '11 at 12:49
2  
I've never seen a line definition that does not include the fact that it is made of 2+ points. Even using an equation of a line if you only have 1 x value in your domain of numbers then it is a point, not a line. –  Rig Sep 20 '11 at 15:34
add comment

Today I wrote about 300 LoC. And I cannot remember any principle that I could violate and did not violated. Refactoring will save my soul, I hope.

If abstraction is dictated by 3d party api - usually it is correct to use inheritance. In domestic design entity must be either abstract, or sealed. Abstract entity potentially must have about 3 inheritors. I do not like one-virtual-method extension points. All above is about my taste. I'm not speaking about interface abstraction, which is completle diffferent story.

share|improve this answer
add comment

If you want a stronger rule of thumb beyond "favor composition over inheritance" then I might suggest something like this :

Of the two ways to specialize an object - Inheritance and Composition - you should use inheritance only when you need your object to be polymorphic ( be substitutable ) for the base class you are specializing.

However like all rules of thumb, once you understand the rule - then you are free to break the rule :)

share|improve this answer
add comment

Favour happens when both candidate qualifies. The problem stated in the question fails on this account, because it only has a composition option.

"Composition could use generalization as well". Does this statement make sense to us? If not then we are not yet ready to grasp the 'favour' rule.

Why we are favouring Composition is that Composition offers more extension/flexiblity possiblities than generalization. This extension/flexiblity refers mostly to runtime/dynamic flexibility(which is achieved with the combination of interfaces and composition).

The benefit is not immediately visible. To see the benefit you need to wait for the next unexpected change request. So in most cases those sticked to generalization fails when compared to those who embraced composition(except one obvious case mentioned later). Hence the rule. From a learning point of view if you can implement a dependency injection successfully then you should know which one to favour and when. The rule helps you in making a decision when you are not sure which one to choose. Again you should be able to see both options in the first place to favour one.

Summary: Composition :The coupling is reduced by just having some smaller things you plug into something bigger, and the bigger object just calls the smaller object back. Generlization: From a 3rd party API point of view defining that a method can be overridden is a stronger commitment than defining that a method can be called (sure win for Generalization). And never forget that with composition you are using generalization too, from a interface instead of a big class. But the whole credit goes to composition unfortunately.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.