Favouring Composition Over Inheritance

Rahmi Cemre Ünal
3 min readAug 22, 2022

--

Composition and inheritance are the two concepts of object-oriented programming that solve similar problems. While their use is not limited to this, they are commonly used when building structures where we want to have common behavior while avoiding code duplication.

It is important to understand the difference between them to decide which one to use and when. So let’s dive into it.

Inheritance

Inheritance is the design strategy to implement a relationship between objects in object-oriented programming. Think of inheritance as an is a relationship. This relation leads to strong behavioral subtyping between classes so when we make a change in the hierarchy, it directly affects the subclasses.

As we can see in the example, we have given the “fly” feature to 2 different airplane types. All the sub-classes have to do is call the fly() method.

But what if we want to use the flying functionality for another class that is not an airplane?

A bird may need only the fly behavior of an Airplane. Deriving each bird from an Airplane class does not make sense, also it breaks encapsulation for the bird to inherit other functionalities belonging to the airplane class such as startEngine() method.

Composition

The composition is typically “has a” or “uses a” relationship. It is just playing it modular: you create an interface similar to the parent class, create a new object, and delegate calls to it. If these objects need not know of each other, it’s quite a safe and easy-to-use composition. Let’s try to implement our previous inheritance example with composition.

One of the important advantages of composition is we do not have to strongly couple our reusable code, unlike inheritance.

We can also use delegation to be able to use it like we are calling superclass method without holding instance reference just like in inheritance.

Also, when we want to add a separate common feature, we can continue to add it without coupling.

If you noticed, Bird class now can support 2 independent functionality. The Kotlin we used in the examples, as well as Java and some other oop-based languages, do not support multiple inheritances. So a class can have only one superclass.

In this context, composition allows us to avoid coupling by using interfaces with individual delegates instead of collecting all the common code in a single base class.

Conclusion

Prefer composition over inheritance as it is more modifiable/easy to change later, but do not use a compose-always approach. If the relation between classes “is a” type and behavior should change from one place, it is okay to use inheritance.

With composition, it’s easy to change individual behavior on the fly since it is interface-based. Inheritance is more rigid as most languages do not allow you to derive from more than one type. Additionally, to decide when to use which one, you can have a look at Liskov Substitution Principle.

--

--

No responses yet