Software/Composition/vs/Inheritance
Summary
- Composition and inheritance are ways to reuse and vary software behavior. Composition places variation in replaceable collaborators; inheritance places it in a parent-child hierarchy. The choice affects coupling, extension, and how behavior is traced.
The Trade-Off
- Choosing composition here means building behavior from collaborators connected through explicit interfaces or delegated calls.
- Gains — independent variation and focused tests; a collaborator can often be replaced without changing the containing object's place in a type hierarchy.
- Costs — additional interfaces, forwarding methods, and wiring. The flow of behavior may be less obvious when spread across collaborators.
- Too far — a web of tiny objects and indirection that makes ordinary behavior hard to trace.
- Choosing inheritance here means specializing a parent class or prototype to reuse behavior and, where justified, express an Software/Inheritance/Is-A relationship.
- Gains — shared implementation and a direct extension point when the specialization preserves the parent's contract.
- Costs — tighter coupling to the parent and its method-resolution rules; a change in shared behavior can affect every descendant.
- Too far — a deep hierarchy built for code reuse, even when some descendants cannot honor the behavior their parent promises. Software/Subtyping explains the resulting substitution problem.
In practice
- Composition often fits when behavior needs independent variation or collaborators can be replaced. Inheritance can fit when a subtype truly preserves the parent contract and the hierarchy represents that relationship.
- The approaches can be combined: a subtype may itself use composition. A choice should follow the needed relationship and its costs.