Low-Level Design6h estimated

Composition Over Inheritance

Difficulty
Importance

The problem

Deep inheritance hierarchies become fragile — a change to a base class can silently break every subclass several levels down, and some combinations of behavior simply don't fit a single-parent hierarchy at all (a FlyingCar is both a Car and a Plane, but can only extend one).

Why now

Inheritance and polymorphism already showed inheritance's power and its Liskov Substitution failure mode; this topic is the direct, practical response — building an object out of smaller, swappable parts instead of a rigid parent-child chain, which is exactly the low-coupling instinct coupling-and-cohesion already established, applied to the specific choice between 'is-a' and 'has-a.'

Mental model

Inheritance asks 'is this a specialized version of that' (is-a) — rigid, single-parent, fragile to base-class changes. Composition asks 'does this contain and delegate to that' (has-a) — an object holds references to other objects that implement specific behaviors, swappable independently, which sidesteps both the single-parent limitation and the deep-hierarchy fragility problem at once.

Requires

Unlocks

Used in

Projects

  • Redesign a rigid inheritance hierarchy (e.g. Duck extends Bird extends Animal, with a FlyingDuck/SwimmingDuck problem) using composition — inject Flying and Swimming behaviors as swappable objects instead
  • Identify a real class in a codebase with a deep inheritance chain and propose a composition-based redesign, listing what becomes easier to change

Examples

  • A Duck that composes a FlyBehavior and a SwimBehavior object can swap either at runtime, while a Duck extends FlyingBird can't represent a duck that's temporarily grounded without awkward workarounds
  • React favors small, composed components over deep class inheritance specifically because composition doesn't create the fragile-base-class coupling deep hierarchies do

Resources

Mastery checklist