When to use inheritance (In JAVA).
“Favor ‘object composition’ over ‘class inheritance’.” (Gang of Four 1995:20)
It is a quote from a book that has been published over 20 years ago. “Design Patterns: Elements of Reusable Object Oriented Software.” And originally I had another introduction in mind but then during research for this article I encountered the following post on StackExchange from Seven A. Lowe. And I decided to quote it fully here. Link to the original post.
Though I think I’ve heard composition-vs-inheritance discussions long before GoF, I can’t put my finger on a specific source. Might have been Booch anyway.
Ah but like many mantras, this one has degenerated along typical lines:
it is introduced with a detailed explanation and argument by a well-respected source who coins the catch-phrase as a reminder of the original complex discussion
it is shared with a knowing part-of-the-club wink by a few in-the-know for a while, generally when commenting on n00b mistakes
soon it is repeated mindlessly by thousands upon thousands who never read the explanation, but love using it as an excuse not to think, and as a cheap and easy way to feel superior to others
eventually, no amount of reasonable debunking can stem the “meme” tide — and the paradigm degenerates into religion and dogma.
The meme, originally intended to lead n00bs to enlightenment, is now used as a club to bludgeon them unconscious.
Composition and inheritance are very different things, and should not be confused with each other. While it is true that composition can be used to simulate inheritance with a lot of extra work, this does not make inheritance a second-class citizen, nor does it make composition the favorite son. The fact that many n00bs try to use inheritance as a shortcut does not invalidate the mechanism, and almost all n00bs learn from the mistake and thereby improve.
Please THINK about your designs, and stop spouting slogans.
We all know how to implement composition, we all know how to implement inheritance. But how is an easy part and it’s just a wrapper, layer around why/when do it. I hope to give you recap argument when to use one over the other. As they both have its usages. And favor one over the other does not mean use one and never the other.
What are we talking about?
I’m Java developer and this article will talk about both concepts in the context of that language. And before I proceed with any arguments I want to explain some things. When I talk about inheritance I have a word extends in mind. Meaning I have a class or abstract class that is the base class for child class. Interface base inheritance is just a tool for polymorphism and nowhere near that dangerous.
When I talk about the composition I mean that the creation of fields of a certain type. Those types have a method/field that can be used by a parent object. Composition can be realized in many ways: Dependency Injection (EJB 3.0, Spring) where instantiation is managed by your run-time, via direct construction of the object using new keyword, etc.
What’s the problem?
And that is a tricky thing to answer. The argument about class (subtype) inheritance is 50 years old. And what’s more even the creator of the OO paradigm had reservations about it and left it out from the original specification (link).
Classic OO concepts: classes, encapsulation, polymorphism don’t get the same heated discussions. They are there and what’s more important all OO languages implement them in a similar way. Where for inheritance it’s all over the map.
Go for example has no inheritance. C++ has ‘multiple inheritance’, JAVA has a single class inheritance, Ruby has mixins, JavaScript has prototype patching, and this article talks about traits (link). And for me, that is a sign of trouble. If the smartest guys in the industry working for over 50 years can’t seem to agree on something how average developers know what to do. I later parts I will have rules that I use when choosing between inheritance and composition.
For me, class-based inheritance realizes two orthogonal purposes. (The exact terms are stolen from this article link)
- Semantical
- Mechanical
Semantical can be further split into two parts.
- One. It expresses the position of a given class in a bigger structure of relations. Where each entity is connected by is a relationship. (Person is a human is a mammal is an animal is livingThing. Would be an example). The problem is that thing A really has just one is a relationship with the thing B. (Person is a human and is a teacher) And not always that relationship is 100% match (Usually we inherit but we want just part of thing B).
- Two. It expresses the contract of the class (At least partially, if we are dealing with abstract classes). The class that inherits from some other class takes responsibility for all public API of a parent class.
Mechanical is where inheritance is all about sharing behavior. All the fields and method implementation form the base class are appended to the child class. Thus making them available for reuse and augmentation. This makes our implementation tightly coupled with the base class. And therefore more brittle. This is especially apparent in deep hierarchies. Where a change in one class leads to changes in 10 other classes. Resulting in a code smell called shotgun surgery.
I think this duality of meaning is where most trouble lies. As some developers use it for code re-usability and some others as a tool for dynamic dispatch (i.e. contract definition). They meet, work on a single project and then accidents happen.
The definitive test for inheritance:
I originally wanted to write a list, how inheritance can fail but it would have less educational value. So instead
When “is a” relationship is violated.
Most common test for an inheritance, that is, why it is first. If you can’s make sense from the statement objectA is objectB. ObjectA can’t inherit from objectB.
public class Car extends Wheel{}
Above example is gibberish. You can’t say Car is a Wheel with a straight face. What you want to say is car has a wheel. And if you are not going to take anything else from this article please remember this.
- “is a” = inheritance (Teacher is a Person)
- “has a” = composition (Car has a Wheel, Teacher has a Pen)
When Liskov Substitution Principle is violated.
So we can say “Electric Duck” is a Duck. Or a Penguin is a Bird. But the first one has to be “turn on” and another can’t “fly”. In these situations, it is the LSP that stop’s us from using inheritance to model that relations. Instead of bringing up the original definition I will quote Venkat’s interpretation:
Services of a derived class should require no more and promise no less than the corresponding services of a base class.
I think it makes things simple. If you feel like you have to modify the contract, or you can fulfill the contract, of the parent class then delegation is something that might be more suitable for your situation.
In business applications, every entity and value object has a set of invariances. For example, Circle has a radius and can’t stretch in one direction. And if you feel like implementing a method would violate one of the promises. Rethink your design.
On a more practical note. I often see this in the code.
public class ElectricDuck extends Duck{
@Override public void fly(){...}
@Override public int altitude(){...}
public void charge(){...}
}
And somewhere else:
if(duck instanceof ElectricDuck){
ElectricDuck electricDuc = (ElectricDuck) duck;
electricDuck.charge();
}
If you see that you have to do any type of conditional logic base on the incoming type you are probably violating LSP.
Another classic example is when you throw an exception. Because the contracts of the two classes do not match.
public class Penguin extends Bird {
@Override
public void fly(){
throw new MethodInvocationException("I can't fly");
}
}
LSP is a very complicated and nuanced subject I highly recommend further reading.
When there is no dynamic dispatch.
And this is the final point. Let’s assume that your inheritance passes the above-mentioned test. But you use inheritance without polymorphism. Don’t. Your model might be correct but, and I can’t emphasize this enough, inheritance is a complexity buster of massive proportions. And should be a choice of a last resort.
public class Figure {
@Override
public String toString() {
return "Figure";
}
public static class Circle extends Figure {
@Override
public String toString() {
return super.toString();
}
}
public static class Ellipse extends Circle {
}
}
Can you immediately tell me what will be printed when I log each instance of the above class. (this is the simplest example I could think.)
If at call site there is a possibility for only one method to be invoked. You are using inheritance only as a tool for code reuse (Mechanical). And in those cases don’t do that. There is just no benefit.
When to use inheritance:
When a child object is a parent object (#1). Parent object methods are either properly overridden or left alone (#2). There is more than one child object that extends parent object and parent object interface is used (#3). The problem is that all these conditions are not met all that often. And that is the reason that you should favor composition over inheritance. To bring back what was said at the beginning, the phrase only exists as a reminder of a complex logic behind it. And I hope that n00bs now can be led back on the path of enlightenment. I’m going to do a second part to this called dangers of inheritance. To supplement this one. But I don’t what to cram too much.