Java · OOP, JVM and backend craft
Why is composition often preferred over inheritance?
Short answer
Inheritance models an is-a relationship and couples a subclass to its parent's implementation. Composition models has-a and delegates behaviour, which is usually more flexible and easier to change.
Subclassing exposes the parent's protected implementation, not just its contract. A change in the parent can break subclasses even when the public API is stable. This is the fragile base class problem. Composition avoids it by holding a reference to a collaborator and delegating explicitly.
public final class Engine {
public void start() {
System.out.println("start");
}
}
public final class Car {
private final Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
public void start() {
engine.start();
}
}When inheritance is still reasonable
- The subtype truly is a specialised version of the parent
- The parent was designed and documented for extension
- The hierarchy is shallow and stable
- Frameworks require a base class, such as some exception or test base types
Composition also makes testing easier because collaborators can be injected. It keeps the public surface small and avoids inheriting methods that do not make sense for the subtype. The Liskov substitution principle is the test: a subtype must be usable anywhere the parent is expected without breaking behaviour.
Follow-ups you should expect
Interviewers use these to check whether the first answer was understanding or memorisation.
- 1What is the fragile base class problem?
- 2How does composition improve testability?
- 3What does the Liskov substitution principle require?
- 4When is inheritance the right choice?
Say it in the interview
Inheritance couples a subclass to the parent's implementation, so a parent change can break children even when the public API looks stable. Composition holds a collaborator and delegates explicitly, which keeps coupling low and makes testing easier. I prefer composition when the relationship is has-a or when behaviour may vary independently. I still use inheritance for genuine is-a cases where the parent is designed for extension.
Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.
Related questions
Reading is step one
Now say it out loud.
Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Java mock interview and get scored feedback on depth, clarity and confidence.