Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Mirnes
Mirnes

Posted on • Originally published atoptimalcoder.net on

     

Composition Over Inheritence

Inheritence is often misused or overused or even forced for several reasons, and they are mostly due to education, misunderstanding or habit. Many developers who studied OOP are introduced with inheritence in early stage and then it stays with them as a default way how to build relationships between objects. Escaping this matrix can be quite challenging, as lacking alternative perspectives often leads to the trap of believing that inheritance is the solution to everything. Here, we will try to find the reasoning behind this way of thinking.

Historical Influence

Early OOP examples often revolved around "is-a" relationships likeCar -> Vehicle, Dog -> Animal, reinforcing inheritance as the primary method of code reuse. We can see this in early OOP literature, such as the influential "Gang of Four Design Patterns", where inheritance is prominently discussed. And then, as a result, developers internalized it as the default design approach.

Inheritance = Code Reuse (Misconception)

Many developers learn that inheritance is the primary way to reuse code. They might think: “If I need to reuse functionality, I must derive from a base class.” This mindset leads to deep hierarchies, tight coupling, even when simpler or more modular solutions (like composition) would work better.

Simplicity of Implementation

Inheritance is Easy to Implement - defining a base class and extending it is straightforward, both conceptually and in terms of syntax. Composition requires more design work, such as defining interfaces or injecting dependencies. Let's show the difference in one simple example:

Inheritence

publicclassVehicle{publicvoidMove(){Console.WriteLine("Moving");}}publicclassCar:Vehicle{}
Enter fullscreen modeExit fullscreen mode

Composition

publicinterfaceIMovable{voidMove();}publicclassCar{privatereadonlyIMovable_movable;publicCar(IMovablemovable){_movable=movable;}}
Enter fullscreen modeExit fullscreen mode

Legacy code

Older systems were built using inheritance-heavy designs, and developers working on these systems are forced to maintain and extend these hierarchies.

Frameworks that Encourage Inheritance

Many frameworks historically relied on inheritance (e.g., GUI frameworks like Swing or .NET's WinForms) where developers extended base classes to customize behavior.

Developers often mimic these patterns without questioning if they're the best solution.

How to Shift Away from Overusing Inheritance

Educate About Composition:

Teach patterns like Strategy, Decorator, and Dependency Injection as alternatives to deep hierarchies. Example: Instead of a Car base class, use aIMovable, IEngine interface and inject behavior dynamically.

Promote Design Principles:

Follow SOLID principles, especially:

  • Single Responsibility: Avoid bloated base classes.
  • Dependency Inversion: Prefer abstractions over specific implementations.

Use Interfaces and Delegation:

Example: Instead ofclass Car : Vehicle, useCar with a composableIEngine orIMovable.

Emphasize Refactoring:

Refactor overly complex hierarchies into flatter, modular designs using composition.

Conclusion

Inheritance is often "forced" because it's historically emphasized, easy to use, and aligns with developers' early understanding of OOP. However, it has significant limitations that make composition a more flexible, scalable, and maintainable choice in many scenarios. By learning and applying composition patterns, developers can avoid rigid hierarchies and design systems that are more robust and adaptable.

Top comments(2)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
danielaragao profile image
Daniel Aragão
  • Work
    Developer
  • Joined

Well, is all about your implementation and design, you can shoot right on target using both, maybe you want to add some more concrete examples of when to use which? or maybe just some reference

CollapseExpand
 
mirnes_mrkaljevic profile image
Mirnes
Software Engineer, well-versed in C#, with experience in JavaScript and Angular, working in logistics.
  • Location
    Neuburg, Bavaria, Germany
  • Joined
• Edited on• Edited

You can use both, for sure. It's just needed to know when to use what.
As said in the post, it is most common that devs are getting into trap of overusing inheritence.
Some of the symptoms when it is overused is multiple levels of inheritence,
ClassA -> ClassB -> ClassC -> ClassD... where you loose the track in hierarchy,
or, when you are in the need to override base functionality in inherited classes,
or when you are not sure if base classes are going to change, etc
For these cases it is better to have more classes with simpler functionalities which are just injected into desired class, as is shown in simple example with Car and IMovable.
Then, also it is easier to test the behaviour of every single class and injecting a mocked dependencies in order to test the final class as well.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Software Engineer, well-versed in C#, with experience in JavaScript and Angular, working in logistics.
  • Location
    Neuburg, Bavaria, Germany
  • Joined

More fromMirnes

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp