50

This question already has an answer here:

Favor composition over inheritance

is very popular phrase. I read several articles and at the end each article says

use inheritance when there is pure IS-A relationship between classes.

An example from this article:

Here between Apple and Fruit there is clear IS-A relationship i.e Apple IS-A Fruit, yet the author has also shown it as Apple HAS-A Fruit (composition) to show the pitfall when implemented with inheritance.

I became somewhat confused here that what is the meaning of statement

use inheritance when there is pure IS-A relationship between classes.

Does using composition over inheritance mean that always try to apply composition even if there is a pure IS-A relationship and leave inheritance only for those cases where composition does not make sense?


  • Why java label? - TT_

7 답변


68

When you use inheritance to reuse code from the superclass, rather than to override methods and define another polymorphic behavior, it's often an indication that you should use composition instead of inheritance.

The java.util.Properties class is a good example of a bad use of inheritance. Rather than using a Hashtable to store its properties, it extends Hashtable, in order to reuse its methods and to avoid reimplementing some of them using delegation.


  • I upvoted since it's a real example that doesn't involve cars, animals or fruit. However, it would be a stronger argument to state how the java.util.Properties extending HashTable has negatively affected design as a consequence. I thought about Liskov Substitution Principle, and I don't think it's a problem. In theory it might be useful for performance/memory reasons to be able to change the storing (hashing) mechanism, but that's not possible with inheritance and might be with composition. - Fuhrmanator
  • Non-rethorical question: Is it not advisable to write a base class, better if abstract, that contains methods that makes perfect sense for all the subclasses to have, and not override any of the base class' methods ? Isn't the Properties extending Hashtable case a good example of bad use of inheritance just because Properties should not care about the whole Hashtable-specific logic and needs only a small subset of that so it shouldn't have extended Hashtable, because it is not one, it just uses one ? - SantiBailors

5

I think this is one of the most discussed point in Object Oriented design. As suggested in the article, composition is always preferred over inheritance. That doesn't mean that you should never use inheritance. You should where it makes more sense (which can debatable).

There are many advantages of using composition, couple of them are :

  • You will have full control of your implementations. i.e., you can expose only the methods you intend to expose.
  • any changes in the super class can be shielded by modifying only in your class. Any clients classes which uses your classes, need not make modifications.
  • Allows you to control when you want to load the super class (lazy loading)


  • My problem is I don't mind moving towards more composition, but for classes with many methods it can be painful to repeat that boilerplate in every derived class. Of course most classes should have only a few methods but in some cases (e.g. GUI Window base class) you can't help having a lot of them. - LegendLength

3

In the article, there is no such phrase:

use inheritance when there is pure IS-A relationship between classes

Moreover, Google did not find it elsewhere except your post.

Instead, the article reads:

Make sure inheritance models the is-a relationship. My main guiding philosophy is that inheritance should be used only when a subclass is-a superclass. In the example above, an Apple likely is-a Fruit, so I would be inclined to use inheritance.

This means, if there is IS_A relationship, try to use inheritance first, and not composition. And there is no preference of using composition over inheritance - each is good for its own role.


  • each is good for its own role. +1 . I think this means it depends on "our motive" for which we are establishing relationship between our classes. If it is "ONLY" for code reuse then Favor composition over inheritance is valid and if the motive is to model the "actual relationship" as it exists in reality between the classes then both inheritance and composition has their own roles. One can choose inheritance if there is pure IS-A relationship "despite" the fact that inheritance has more problems than composition like strong coupling, otherwise opt for composition. Am i right? - a Learner
  • Code reuse is a powerful motive, it alone may be enough to chose inheritance. Strong coupling can be considered advantageous rather than problem in many cases. And in many languages (java), inheritance is just easier than composition. Only experience can give you feeling of what is right approach for given case, there are no strict rules. - Alexei Kaigorodov

3

Also, I would like to add that Decorator pattern is an example where you can use composition over inheritance and add responsibilities to objects dynamically. The example of Decorator pattern is mentioned in Effective Java in the item "Favor Composition over Inheritance". To take an example from Java API; BufferedReader decorates a Reader (instead of extending FileReader, PipedReader, FilterReader etc) and hence has the capability to decorate any kind of Reader. Buffering functionality is attached to these readers at runtime which is the Decorator pattern.

Here extension by subclassing would be impractical.


3

I guess a good guideline would be:

When there is an IS-A relationship, use inheritance. Otherwise, use composition.

The reason for this is related to another concept in Object Oriented Design - polymorphism. Polymorphism is a feature of many OOP languages where an object can be used in place of another object, provided that the class of the first is a subclass of the second.

To illustrate, imagine if you have a function that takes in a type of animal. When you use inheritance, you only have one function:

void feed( Animal a );

Polymorphism assures us that any subclass of animal we put in will be accepted. Otherwise, we will be forced to write one function for each type. I think the benefits of this outweighs its disadvantages (ex. reduced encapsulation).

If there is no IS-A relationship, I think polymorphism won't be very effective. It would thus be better to use composition and have enhanced encapsulation/isolation between classes.


  • If there is no IS-A relationship, I think polymorphism won't be very effective. It would thus be better to use composition and have enhanced encapsulation/isolation between classes.+1 - a Learner

2

Use inheritance when the relationship is permanent. Do not use extension just to get free behavior. This is what they are referring to on the IS-A example. Only extend if the extending class truly is an extension of the parent. There will be times when it's not cut and dry, but in general. Composition provides flexibility in the future too if you need to extend from the "right" class.

This is an old but great article on extends:

http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html


0

I would say no. In the fruit/apple scenario, it makes good sense to use inheritance. The author of the article confirms that, too: "In the example above, an Apple likely is-a Fruit, so I would be inclined to use inheritance".

If your subclass is clearly a superclass, inheritance is fine. In practice though, you'll find many more situations that are better solved using composition.


  • "If your subclass is clearly a superclass" ? - Simon Nickerson
  • @SimonNickerson "If <what-your-subclass-models> clearly IS-A <what-your-superclass-models>" - Joffrey

Linked


Related

Latest