Composition & Inheritance
- Comparison of composition and inheritance design approaches in JavaScript.
Introduction to Code Reusability in OOP
One of the main goals of Object-Oriented Programming is code reuse.
JavaScript provides two major approaches to reuse behavior:
Inheritance
Composition
Both are powerful, but they solve problems in different ways.
Understanding when to use inheritance and when to use composition is very important for:
Clean architecture
Scalable applications
Interview preparation
Real-world projects
Composition vs Inheritance
What Is Inheritance ?
Inheritance is an OOP concept where a child class inherits properties and methods from a parent class.
It represents an “is-a” relationship.
Simple Definition
Inheritance allows one class to reuse the functionality of another class by extending it.
Inheritance Syntax in JavaScript
class Parent {
method() {
console.log("Parent method");
}
}
class Child extends Parent {
childMethod() {
console.log("Child method");
}
}
let obj = new Child();
obj.method();
obj.childMethod();
How Inheritance Works
Child automatically gets access to Parent methods
No need to rewrite common code
Achieved using the extends keyword
Real-Life Example of Inheritance
Animal → Dog
Vehicle → Car
Employee → Manager
A Car is a Vehicle
Realistic Inheritance Example
A child class inherits and uses methods from a parent class along with its own.
class Animal {
eat() {
console.log("Eating...");
}
}
class Dog extends Animal {
bark() {
console.log("Barking...");
}
}
let dog = new Dog();
dog.eat();
dog.bark();
Advantages of Inheritance
Code reuse
Clear hierarchy
Easy to understand initially
Familiar OOP structure
Disadvantages of Inheritance
Tight coupling between classes
Changes in parent may break child
Deep inheritance chains become complex
Not flexible for dynamic behavior
What Is Composition ?
Composition is an approach where objects are built by combining smaller, reusable objects, instead of extending a class.
It represents a “has-a” relationship.
Simple Definition
Composition means creating objects by combining functionality from multiple independent objects.
Mixins Example
Combines multiple objects to share behavior without using inheritance.
const canEat = {
eat() {
console.log("Eating...");
}
};
const canBark = {
bark() {
console.log("Barking...");
}
};
function createDog() {
return Object.assign({}, canEat, canBark);
}
let dog = createDog();
dog.eat();
dog.bark();
How Composition Works
Behavior is copied or shared
No class hierarchy
Objects are flexible and modular
Easy to add or remove behavior
Real-Life Example of Composition
A Smartphone has:
Camera
Music player
GPS
Internet browser
Composition Example
Combines multiple behaviors into an object using composition.
const canLogin = {
login() {
console.log("User logged in");
}
};
const canLogout = {
logout() {
console.log("User logged out");
}
};
function createUser(name) {
return {
name,
...canLogin,
...canLogout
};
}
let user = createUser("Rahul");
user.login();
user.logout();
Advantages of Composition
Loose coupling
High flexibility
Easy to maintain
Avoids inheritance problems
Encourages reusable logic
Disadvantages of Composition
Slightly more code initially
Requires good design thinking
Less familiar to beginners
Composition vs Inheritance (Core Comparison)
When to Use Inheritance ?
Use inheritance when:
There is a clear is-a relationship
Class hierarchy is shallow
Behavior is stable
Structure is unlikely to change
Example:
Employee → Manager
Shape → Circle
When to Use Composition ?
Use composition when:
Behavior needs to be flexible
Multiple behaviors are shared
App needs scalability
Avoiding deep inheritance trees
Example:
User roles
Feature-based systems
Permissions
Plugins
Industry Rule (Important)
“Favor Composition over Inheritance”
This is a widely accepted best practice in modern JavaScript and software design.
Common Beginner Mistakes
Using inheritance everywhere
Creating deep inheritance chains
Mixing unrelated logic in parent classes
Not understanding is-a vs has-a
Overengineering simple problems
Best Practices
Prefer composition for shared behavior
Use inheritance only when relationship is natural
Keep inheritance trees shallow
Design reusable behavior modules
Focus on flexibility and maintainability