Inheritance vs. Composition
About
In object-oriented programming, Inheritance and Composition are two fundamental techniques used to achieve code reuse and build relationships between classes. Though they aim for similar goals, they approach the problem differently and each has its own advantages and trade-offs.
What is Inheritance ?
Inheritance is a mechanism where a class (subclass or child) derives from another class (superclass or parent), inheriting its fields and methods.
Defines an "is-a" relationship.
Promotes code reuse by allowing subclasses to inherit behaviour.
Supports method overriding for polymorphism.
class Animal {
void eat() {
System.out.println("This animal eats food.");
}
}
class Dog extends Animal {
void bark() {
System.out.println("The dog barks.");
}
}
Usage
Dog d = new Dog();
d.eat(); // inherited from Animal
d.bark(); // defined in Dog
What is Composition?
Composition is a design technique in which a class is composed of one or more objects of other classes, allowing you to build complex types by combining simpler ones.
Defines a "has-a" relationship.
Offers greater flexibility and modularity.
Behavior is achieved by delegating tasks to internal objects.
class Engine {
void start() {
System.out.println("Engine starts");
}
}
class Car {
private Engine engine = new Engine();
void startCar() {
engine.start(); // delegation
System.out.println("Car is running");
}
}
Usage
Car car = new Car();
car.startCar();
Comparison
Relationship Type
"is-a"
"has-a"
Coupling
Tightly coupled (inherits implementation)
Loosely coupled (uses delegation)
Flexibility
Less flexible; tightly bound hierarchy
More flexible; can switch components
Code Reuse
Achieved through superclass
Achieved through composed objects
Method Overriding
Supports polymorphism
Doesn’t support overriding, but can delegate
Runtime Changes
Difficult
Easier to modify components
Hierarchy Depth
Can become deep and complex
Flatter and easier to manage
Example
Dog is-a Animal
Car has-a Engine
When to Use Inheritance & Composition ?
Use inheritance when:
The subclass is a specialized version of the superclass.
There is a clear is-a relationship.
We want to leverage polymorphism for method overriding.
The base class provides stable and reusable behavior.
Use composition when:
We need flexibility and maintainability.
We want to change behavior at runtime.
We want to reuse functionality without forming a strict hierarchy.
We want to avoid the problems of deep inheritance trees.
Last updated