Favor Composition Over Inheritance part 1 | Source: Coding Delight

I have been discussing “Composition over Inheritance” with my teammates a lot on the last few weeks, and I really love to learn this kinds of patterns, but this one is kind of tricky, in the sense that it is not REALLY clear what is the benefit and, if misused, can bring more troubles than benefits.

So I found this post, from the Coding Delight Blog, which, at least for me, help to understand the idea behind the pattern.

“Favor composition over inheritance” is a phrase that I hear spoken a lot but which describes a concept I rarely actually see in real world code.  Every developer seems to know about it but few developers seem to actually put it into practice. This post will be looking at inheritance and some of the pitfalls of trying to create your domain model primarily through inheritance.

I can only assume that the reason why inheritance is so overused in real world code is due to the way that it is taught.  Back, far too many years ago, while I was still studying at university, the concepts of inheritance and polymorphism where both taught side by side, very early in the object-oriented programming course.  It seems as though these lessons were particularly memorable, because so much real-world code has giant inheritance chains.  We have ObscuredItems inheriting from DataItems inheriting from BasicItems which inherit from Items which inherit from BaseObjects.  Often times you will have to go five or six classes deep to find the root cause of a bug.

Favoring composition over inheritance helps us flatten those structures.  To illustrate this, I am going to take a look at a very simple problem.

I want to model real-world cars.  Specifically, I initially want to model the changes that a driver is applying to each car.  The customer in this case only wants me to model a Toyota Corolla.  The class should also have a string for the manufacturer name.  In this case I will deliberately favor inheritance.

Firstly, I’ll set up an abstract BaseCar class where I will define what I need: 4 wheels, a method for acceleration, a method for turning left and a method for turning right.

Next up, I will implement the functionality in my concrete car class.

Finally, I will then implement a concrete ToyotaCorolla class.

All fairly straight forward.  We have a nice little inheritance chain that seems to make sense (although perhaps I could have done away with the BaseCar class).

I submit this code to the customer and they are very happy.  They’re so happy that they will pay me more money to add extra features.  They now want me to implement a ToyotaCorollaSports class, which contains a rear-wheel drive version of the car.  In all other aspects it’s the same car, it’s only that the rear wheels are now powering the car.

Simple enough, I can inherit from the ToyotaCorolla and override the accelerate method.  I make the change and submit it to the customer.  They like what they see.

Two weeks later the customer has come back.  They love what we’ve done and want us to implement HondaCivic and HondaCivicSports classes.  Now we run into our first real problem.  The rear-wheel drive code is actually in the concrete ToyotaCorollaSports class.  What we need to do now is actually refactor our Car class into FrontWheelDriveCar and RearWheelDriveCar.  HondaCivic and ToyotaCorolla can then both inherit from the FrontWheelDriveCar class and the sports editions can both inherit from the RearWheelDriveCar class.

Our customers are very happy with what we have done so far and decide to commission us to create a four-wheel drive Mitsubishi Titan.

So we now have to create an AllWheelDriveCar and inherit from that for our Mitsubishi Titan.

class diagram
Finally, the customer comes along and asks us to model for them a new experimental four-wheel drive buggy that is designed to go on sand and turns with all four wheels.  A two-wheel drive buggy is also available (it also turns with all four wheels).

Now we have a problem.  We will obviously be deriving from our four-wheel drive class for the four-wheel drive model and the two-wheel drive class for the two-wheel drive model, but we will also have to override our TurnLeft and TurnRight methods in both classes, and the code will be duplicated.

Arggg!  Duplicated code is the enemy of maintainability. The best solution to this problem is to switch our thinking. Instead of inheriting all of our functionality, we should compose our classes from pieces of related functionality.

Next up: a better way to solve the same problem.

Also published on Medium.