https://en.wikipedia.org/wiki/Composition_over_inheritance
Inheritance: https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)
Composition: https://en.wikipedia.org/wiki/Object_composition
Aggregation: https://www.youtube.com/watch?v=pqQAHA1XjJk
In this file, “inheritance” refers exclusively to class-based implementation inheritance, meaning rigid superclass–subclass chains where concrete subclasses inherit both structure and behavior from concrete superclasses. Such implementation inheritance creates tight coupling, fragile base classes, deep hierarchies, constructor hell, and unit-test-unfriendly systems.
This does not include interface subtyping (which is fine).
An unsorted list of drawbacks of implementation inheritance and why composition, aggregation, or delegation is often a better alternative:
- Implementation inheritance is widely recognized as a problematic approach to code reuse.
- Implementation inheritance often leads to tight coupling, fragile base classes, and complex hierarchies that are difficult to maintain and extend.
- Languages like Go, Zig, Gleam, Haskell, Elixir, Elm, Julia, etc. have intentionally omitted alternatives to implementation inheritance from their design. This isn’t an oversight.
- IntelliJ IDEA offers a menu option to refactor code by replacing implementation inheritance with delegation, but not the other way around. https://www.jetbrains.com/help/idea/replace-inheritance-with-delegation.html
- The Fragile Base Class Problem.
Changes to a parent class can unexpectedly break child classes, even when the changes seem safe. Child classes depend on implementation details of their parents, making the system brittle. - Deep Implementation Inheritance Hierarchies.
Complex implementation inheritance trees become difficult to understand, maintain, and debug. The deeper the hierarchy, the harder it becomes to trace behavior and understand the flow of method calls. - The Diamond Problem.
In languages supporting multiple implementation inheritance, ambiguity arises when a class inherits from two classes that share a common ancestor. The system cannot determine which version of inherited methods or properties to use. - Tight Coupling.
Implementation inheritance creates strong dependencies between parent and child classes. Child classes become tightly bound to their parent's implementation, reducing flexibility and making changes risky. - Violation of Encapsulation.
Child classes often need access to parent class internals, breaking encapsulation principles. This exposure of implementation details makes the code harder to maintain and more prone to bugs. - The Yo-Yo Problem.
Understanding program flow requires constantly jumping up and down the implementation inheritance hierarchy to trace method calls and understand behavior, making debugging and comprehension difficult. - Inflexibility at Runtime.
Implementation inheritance relationships are fixed at compile time, preventing dynamic behavior changes that might be needed during program execution. - Method Override.
Complications Overriding methods can lead to unexpected behavior, especially when parent methods are called implicitly or when the Liskov Substitution Principle is violated. - Constructor Complexity.
Managing constructor calls through implementation inheritance chains becomes complex, especially ensuring proper initialization order and parameter passing. - Unit Testing Difficulties!
Inherited behavior makes unit testing more complex since you must consider all inherited functionality, not just the class being tested.
These issues have led many developers to favor composition over implementation inheritance to create more flexible and maintainable code.
Videos:
- The Flaws of Inheritance, CodeAesthetic
https://youtu.be/hxGOiiR9ZKg?si=9oeuYiJT1f62J2Qd - Why OOP inheritance sucks, Stefan Mischook
https://www.youtube.com/watch?v=da_Rvn0au-g - Compositional Software Design - Better, Smaller Code, Faster
https://www.youtube.com/watch?v=rmEh3E1ZIfU - Should you use OOP programming in 2018?, Stefan Mischook
https://youtu.be/_2gHV0WeXjo?si=U50h8wRAW2ua26Zf&t=163 - Composition Vs Inheritance - Why You Should Stop Using Inheritance, Web Dev Simplified
https://youtu.be/nnwD5Lwwqdo?si=cLAQoBxJjSeboPDF - Большие проблемы наследования в ООП, ExtremeCode
https://www.youtube.com/watch?v=-n6784KeQMs - Only Use Inheritance If You Want Both of These, Christopher Okhravi
https://www.youtube.com/watch?v=C3B5IIlt4-0&t=263s - Object-Oriented Programming is Bad, Brian Will
https://youtu.be/QM1iUe6IofM?si=ADS7cWFGwQED96P4 - Jonathan Blow on the Problem with Object Oriented, Jonathan Blow Clips
https://www.youtube.com/watch?v=04ksL1hf_p8 - Why do programmers have problems with OOP?, Fredrik Christenson
https://youtu.be/9PSinCLShUA?si=fFCzwVCmVVJIDxNS - Composition over Inheritance: A Practical Guide, Mohamad Rejeb
https://youtu.be/X_weppAAQBs?si=08E8EHpM0WhciwjB - Casey Muratori – The Big OOPs: Anatomy of a Thirty-five-year Mistake
https://www.youtube.com/watch?v=wo84LFzx5nI&t=2s
Text:
- Cognitive load is what matters
https://minds.md/zakirullin/cognitive#inheritance
https://github.com/zakirullin/cognitive-load?tab=readme-ov-file#inheritance-nightmare - Inheritance vs. Composition
https://mccue.dev/pages/7-27-25-inheritance-vs-composition - React, Composition vs Inheritance
https://legacy.reactjs.org/docs/composition-vs-inheritance.html - https://asserttrue.blogspot.com/2009/02/inheritance-as-antipattern.html
- https://blogs.oracle.com/javamagazine/post/java-inheritance-composition
- https://en.wikipedia.org/wiki/Composition_over_inheritance
- https://kotlinlang.org/docs/delegation.html
- https://refactoring.guru/replace-inheritance-with-delegation
- https://www.quora.com/Why-is-Golang-considered-object-oriented-when-it-has-no-classes-and-inheritance
- https://news.ycombinator.com/item?id=24443947
- https://clearcode.petokrisa.hu/oop/do-not-use-inheritance
- https://stackoverflow.com/questions/49002/prefer-composition-over-inheritance
- https://stackoverflow.com/questions/3294348/what-are-the-disadvantages-of-using-inheritance-as-a-way-of-reusing-code
- https://syntactic-sugar.dev/blog/nested-route/composition-over-inheritance?utm_source=chatgpt.com
- https://theburningmonk.com/2015/03/this-is-why-you-need-composition-over-inheritance/?utm_source=chatgpt.com
- https://www.infoworld.com/article/2161393/a-conversation-with-james-gosling.html
- https://pragprog.com/tips/
##Quote by Joe Armstrong:
The problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.
Source: pragprog.com/tips
-
Care About Your Craft
Why spend your life developing software unless you care about doing it well? -
Don’t Live with Broken Windows
Fix bad designs, wrong decisions, and poor code when you see them. -
Critically Analyze What You Read and Hear
Don’t be swayed by vendors, media hype, or dogma. Analyze information in terms of you and your project. -
Don’t Pay Inheritance Tax
Consider alternatives that better fit your needs, such as interfaces, delegation, or mixins. -
Delegate to Services: Has-A Trumps Is-A
Don’t inherit from services — contain them. -
Prefer Interfaces to Express Polymorphism
Interfaces make polymorphism explicit without the coupling introduced by inheritance. -
Decoupled Code Is Easier to Change
Coupling ties things together, making it harder to change just one thing. -
Eliminate Effects Between Unrelated Things
Design components that are self-contained, independent, and have a single, well-defined purpose. -
Good Design Is Easier to Change Than Bad Design
A thing is well designed if it adapts to the people who use it. For code, that means it must adapt by changing. -
Make It Easy to Reuse
If it’s easy to reuse, people will. Create an environment that supports reuse.
https://discourse.julialang.org/t/why-there-is-no-oop-object-oriented-programming-in-julia/86723/9