Composition vs Inheritance — Why 'Favor Composition Over Inheritance'
Fast recall
Quick revision
Core answer
java.util.Stack extends Vector is the canonical Java mistake — Stack inherits insertElementAt(), violating the stack contract permanently. Composition holds behavior via interface reference: swappable at runtime, mockable in tests, not limited to single inheritance. Use inheritance only for genuine IS-A with permanent subtyping.Whether the candidate understands why the GoF principle exists — not just 'composition is better' but the specific design problems inheritance causes and when inheritance is still the right choice
Saying 'composition is always better' without nuance. Not understanding the fragile base class problem. Using inheritance purely for code reuse instead of modeling genuine IS-A relationships
Demonstrate the fragile base class problem with a concrete example. Show how composition with strategy/delegate pattern gives the same code reuse without the coupling. Know that Java's own API has inheritance mistakes (Stack extends Vector)
Interview-ready guide
Interview answer
Composition and inheritance are two fundamental approaches to code reuse and behavioral flexibility in Java. Inheritance uses extends to acquire a parent's implementation — but it also creates a permanent coupling to every implementation detail of that parent. Composition instead holds behavior through interface references, which makes it loosely coupled, swappable at runtime, and straightforward to test.
The fragile base class problem:
- When a child class
extendsa parent, it silently inherits every dependency and behavior of that parent — change the parent's internals and children break, often in ways that aren't immediately obvious - Java's
Stack extends Vectoris the canonical mistake: Stack inheritedinsertElementAt()andremoveElementAt(), which permanently violate the LIFO contract — callers can insert at position 3 of a "stack" - The Javadoc still says to use
Dequeinstead; the class can't be fixed without breaking backward compatibility — that's how permanent the coupling is
Why composition is more flexible:
- Composition holds behavior via an interface reference —
ReportGeneratorhas aReportFormatterfield — which means you can injectPdfFormatter,CsvFormatter, orExcelFormatterwithout creating a new subclass for each - Adding new capabilities (logging, retry, auditing) means injecting more collaborators as separate fields, not extending deeper into a class hierarchy
- Composed dependencies can be mocked in isolation — unit testing a class that
extendsrequires testing all parent behavior too; composition lets you test each piece independently
When inheritance is the right choice:
- Genuine IS-A with a permanent relationship that will never need swapping:
Dog extends Animalis appropriate ifDogreally is an Animal in every context - Template method pattern: the parent defines the algorithm skeleton and subclasses fill in well-defined abstract steps — a clean use of inheritance with clear boundaries
I recommend defaulting to composition. Reach for inheritance only when the IS-A relationship is genuine and permanent, and behavior never needs to be swapped at runtime.
Composition vs Inheritance — Why 'Favor Composition Over Inheritance'
Direct Answer
Favor composition — inheritance couples the subclass to every implementation detail of the parent (fragile base class problem). Change the parent, children break silently. java.util.Stack extends Vector is the canonical Java mistake — Stack inherits insertElementAt(), violating the stack contract permanently. Composition holds behavior via interface reference: swappable at runtime, mockable in tests, not limited to single inheritance. Use inheritance only for genuine IS-A with permanent subtyping.
Common Mistakes & Pitfalls
Saying 'composition is always better' without nuance. Not understanding the fragile base class problem. Using inheritance purely for code reuse instead of modeling genuine IS-A relationships
Check your understanding
Answer these without looking back at the article.
- What is the fragile base class problem — give a concrete example of a parent change silently breaking a child?
- Why is Stack extends Vector considered a design mistake, and what should you use instead?
- How does the strategy pattern use composition to replace a class hierarchy?
- What is the open/closed principle and how does composition help achieve it without modifying existing classes?
- When is inheritance still the right design choice over composition?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.