Skip to content

Composition over Inheritance — Notes#

Why it usually wins#

  • Behaviours can be swapped at runtime.
  • Easier to test (mock the collaborator).
  • Avoids deep hierarchies (which are hard to reason about).
  • Sidesteps multiple-inheritance issues.

When inheritance is fine#

  • Closed, stable hierarchies (Shape → Circle/Rect/Triangle).
  • Templates and frameworks that explicitly require it (Spring's HandlerAdapter, Android Activity).
  • Trivial extension where overriding is the natural mechanism.

"Favor composition" ≠ "never inherit"#

  • Single-level inheritance is often perfectly fine.
  • Inheritance chains > 2 levels are a smell.
  • "Marker interfaces" or sealed hierarchies model algebraic data types cleanly.

Refs#

  • Effective Java — Items 18 (favor composition over inheritance), 19 (design for inheritance or prohibit it).
  • Design Patterns (GoF) — many patterns are composition-based alternatives to inheritance.
  • Go: design and evolution talks — Go intentionally drops inheritance.