Chapter 97·Beginner·8 min read
Composition Over Inheritance: The Advice You'll Hear Most
A plain-English, language-agnostic guide to composition over inheritance — the difference between 'is-a' and 'has-a', why deep class trees turn brittle, and how building objects from parts keeps designs flexible.
July 15, 2026
You now know the four pillars: encapsulation, abstraction, inheritance, and polymorphism. The single most repeated piece of OOP design advice sits on top of them: favour composition over inheritance. This chapter explains what that means and why it's such common counsel.
Two ways to build a bigger object
There are two ways to give an object more capability:
- Inheritance — an is-a relationship. A
SavingsAccountis anAccountand inherits its structure. - Composition — a has-a relationship. An
Accounthas aTransactionLogand has anInterestPolicy, holding them as parts and delegating to them.
class Account:
log = new TransactionLog() # has-a
policy = new InterestPolicy() # has-a
method addInterest():
deposit(policy.compute(balance)) # delegate to the partComposition builds bigger objects by combining smaller ones and passing work to them, rather than climbing a class tree.
Why composition is usually preferred
Inheritance is rigid: the relationship is fixed at definition time, the subclass is tightly bound to the parent's internals, and deep trees become the fragile base class problem — a change up top ripples unpredictably down. Composition is looser:
- Swappable parts — give the account a different
InterestPolicyand its behaviour changes, without touching the account or any class tree. You can even swap it at runtime. - Mix and match — combine capabilities freely instead of trying to express every combination as a subclass (the classic explosion where you end up wanting
SavingsCheckingOverdraftAccount). - Looser coupling — a part is used through its interface, so it's far less entangled than a parent a subclass depends on.
The test, and the caveat
When you're unsure which to use, run the same test from the inheritance chapter:
- Is B genuinely a kind of A? → inheritance may fit.
- Does B merely need what A does? → give B an A as a part (composition).
Recap
- Composition ("has-a") builds objects by combining and delegating to smaller parts; inheritance ("is-a") builds them by extending a parent.
- Composition is usually preferred for flexibility: parts are swappable, capabilities mix and match, and coupling is looser.
- Deep inheritance trees turn brittle; composition sidesteps the fragile-base-class trap and the subclass explosion.
- It's a default, not a ban — inherit for genuine, stable "is-a" relationships; otherwise, compose.
That completes the concept-first tour of OOP: objects and classes, the four pillars, and the design instinct that ties them together. From here, the ideas transfer to any object-oriented language you pick up — the syntax changes, the concepts don't.