Composition over Inheritance – When to Pick Each

Many developers learn about inheritance first, but as your projects become more complex, you'll find that composition is often a safer, more flexible way to build your code.

Inheritance lets you create a new class from an existing one, but if you overuse it, your code can become tangled and hard to change. Composition means building classes using smaller building blocks—combining them as needed, like snapping together Lego pieces.

Building a robot with different attachable parts
Imagine you are building a robot. Instead of having one robot that can do everything, you add only the parts you need—wheels, arms, tools. You can easily swap out or upgrade each part without affecting the others.

Real-Life Analogy: Building a Robot with Parts

Suppose you have a basic robot, and you want to give it different abilities. Instead of making a long chain of robot types (RobotDog, RobotDogWithArms, RobotDogWithArmsAndWheels), you simply attach or detach the abilities you need—wheels for moving, arms for grabbing, and so on.

  • Inheritance is like getting a robot that comes with everything built-in—hard to customise.
  • Composition is like having a box of parts, so you can build any robot you want.
  • If you want a robot with new features, just attach more parts.

Benefits of Composition

Using composition gives you much more control and flexibility. You avoid the problem of deep inheritance trees, and your classes stay simple.

  • Flexible and reusable code pieces
  • Easier to test and update individual features
  • Less risk of breaking things when making changes

When to Use Each Approach

Inheritance is best when classes share a clear "is-a" relationship (like Cat is a type of Animal). Use composition when you want to mix and match features or behaviours.

  • Use inheritance for strong relationships (e.g. Dog inherits Animal).
  • Use composition to add features (e.g. a robot can have many abilities).

Common Mistakes to Avoid

Beginners often create complicated class hierarchies using inheritance when simple composition would be enough. This makes code harder to manage and reuse.

  • Don't create deep inheritance trees unless truly necessary.
  • Favour simple, reusable components.

Final Thoughts

Composition keeps your code flexible, simple, and ready for future changes. Next time you design a class, think about building with parts instead of inheriting everything.