Composition Over Inheritance
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
- Inheritance & PolymorphismLow-Level Design
This topic is the direct, motivated alternative to inheritance; you need inheritance's real limitations (rigidity, fragile base classes, single-parent constraint) already experienced before composition's advantages register as solving a real problem rather than an arbitrary preference.
Unlocks
Used in
- Strategy and Decorator design patterns, both built entirely on composition instead of inheritance
- React's component model, which favors composing components over class inheritance hierarchies
- Game engine entity-component systems, an extreme, deliberate application of composition over inheritance
- Avoiding the 'fragile base class' problem in long-lived, deeply inherited codebases
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
- I can explain the difference between an 'is-a' and a 'has-a' relationship with examples
- I can redesign an inheritance hierarchy using composition instead
- I can explain the 'fragile base class' problem and how composition avoids it
- I can decide, for a new design, whether inheritance or composition better fits the relationship