Loading
Loading
Object-Oriented Foundations
Two ways to reuse behaviour, taught together because choosing wrongly is the most common design mistake there is.
By the end of this chapter
Concept
Is the subtype a permanent, total specialisation of the supertype — true for the object's whole life, in every context? If yes, inheritance may fit. If it is one aspect of behaviour that could vary independently, compose.
A Car is permanently a Vehicle; that is not a role it plays sometimes. But a Car's pricing rule, logging destination and fuel strategy are all things that could vary independently, and none of them should be in its type.
Suppose notifications vary by channel — email, SMS, push — and by urgency — normal, batched, immediate. With inheritance you need a class per combination: EmailNormal, EmailBatched, EmailImmediate, SmsNormal, and so on. Three channels and three urgencies is nine classes, and a fourth channel makes twelve.
With composition, a Notifier holds a Channel and a DeliveryStrategy. Three plus three is six classes, a fourth channel makes seven, and any combination is a constructor call rather than a new class.
| Inheritance | Composition | |
|---|---|---|
| Two dimensions, n and m | n × m classes | n + m classes |
| Changing behaviour at runtime | Impossible — type is fixed | Swap the collaborator |
| Coupling to the reused code | Total, including protected internals | Only the interface |
| Testing one piece alone | Must construct the whole hierarchy | Construct the one class |
A subclass can see its parent's protected state and depends on the order in which the parent calls its own methods. Change a parent's internal call order — a refactor that looks entirely private — and a subclass that overrode one of those methods can break, silently, without either file looking wrong.
Polymorphism — calling the same method and getting different behaviour — is the genuinely valuable part, and it does not require inheritance. An interface gives you exactly that with none of the coupling, which is why most modern designs have wide, shallow interface hierarchies rather than deep class trees.
Sign in to keep a note here. It is free, and nobody else can see it.
Sign inWhat this chapter was for: