Composition over inheritance for less coupling

Daniele Scillia (Dan The Dev)
Dan the Dev
Published in
4 min readApr 30, 2021
Photo by Ryland Dean on Unsplash

Composition over inheritance.

How many times have you read and heard this? I think it’s the web’s most clickbait topic about Object-Oriented Programming.

Today it’s my turn to talk about it because I’ve always struggled to understand what it meant and I think we often use examples that are too complex while the concept is powerful yet simple!

Inheritance is often misused

First of all, I’ll try to explain the problem that Composition solves: inheritance is often used inappropriately, with the only goal to avoid code duplication.

DRY is definitely a good principle, but this is not the purpose of Inheritance, which instead aims to express a very precise type of relationship: an “is-a” relationship. The subclass expresses a concept that is a subset of the concept of the superclass.

I’ll try to better explain the concept with an example (hopefully simpler than the examples I blamed at the beginning of this article): when we have a class Dog that extends the class Animal, we are saying that a dog “is-a” animal. If we replace the instance of Dog() with the instance of Animal(), the code still makes sense.

The last line of code doesn’t work, of course, but semantically it makes sense

If you think it this way, Inheritance is connected to Liskov’s Substitution Principle, one of the SOLID principles, which basically brings semantics in support of programming: the principle states that if in the code we replace a class with its superclass, the code should have the same meaning as before, because the concept of inheritance is the subset concept: dogs are a subset of animals.

In other words, we can express this principle by saying that the subclass must keep the promises made by its superclass; this also means that, in the example of the image, Animal was a class, the last line should also keep working.

Composition has its own meaning

That was an example of correct usage, now let’s see an incorrect usage example.

Let’s assume we have a Person class, which represents the concept of person, so for example it could have attributes such as gender, date of birth, name, etc; then we also have a Wallet class, which represents the concept of a wallet and so it will have attributes such as the amount of money, material, color, etc; at some point, we need to give the person the possibility to make purchases.

The typical mistake people make is to have the Person class extend the Wallet class to give it access to the money quantity attribute and payment behavior.

A Person is a Wallet? Doesn’t make sense!

But, as mentioned, we are implicitly declaring that a Person “is a” Wallet. Obviously, this makes no sense from a semantic point of view; Liskov’s substitution principle cannot be applied because Person class cannot keep the promises made by the Wallet class.

The correct approach, in this case, is to use Composition: the Person class is therefore composed of attributes that have other objects as type, in particular in our example we will have a wallet attribute that is of type Wallet.

From a semantic point of view, the composition is a relation of type “has-a”, we are therefore implicitly declaring that a person “has a” wallet, which is much more correct from an expressive point of view.

A Person “has a” Wallet: that completely makes sense!

To conclude, it’s fair to say that even when semantically inheritance seems correct, there are cases where we should still prefer composition to improve the design.

For example, imagine implementing the concept of Pizza: with inheritance, we should create a subclass for each type of Pizza we want to offer, with an explosion of classes; with composition, we can say that a Pizza is composed of ingredients, each one expressed with an attribute; we can then manage the creation of the specific Pizza we need with a Creational Design Pattern, for example, the Builder Pattern.

--

--

Daniele Scillia (Dan The Dev)
Dan the Dev

Software Engineer @TourRadar - Passionate Dev, XP Advocate, passionate and practitioner of Agile Practices to reach Technical Excellence