Composition
About
Composition is an object-oriented design principle where one object contains another object instead of inheriting from it. It is based on the "has-a" relationship rather than an "is-a" relationship (which is used in inheritance).
Key Idea: Instead of extending a class (inheritance), we create an instance of another class as a field inside our class and use its functionality.
Composition is not considered as one of the four fundamental OOP principles (Encapsulation, Abstraction, Inheritance, and Polymorphism). However, it is an important design concept within OOP.
Types of Composition
There are two main types of composition:
1. Strong Composition (Composition) – "Lifelong Dependency"
The contained object CANNOT exist without the containing object.
Strong ownership: If the main object is destroyed, the contained object is also destroyed.
Represented by a filled diamond in UML.
Example: A Car
has an Engine
(An Engine cannot exist without a Car)
2. Weak Composition (Aggregation) – "Independent Relationship"
The contained object CAN exist independently.
Weak ownership: If the main object is destroyed, the contained object can still exist.
Represented by an empty diamond in UML.
Example: A University
has Students
, but students can exist without a university.
Better Reusability: Students can exist outside of a university.
Composition vs. Inheritance
Comparison
Feature
Composition (Preferred)
Inheritance (Use with Caution)
Relationship
"Has-a" (Car has-a Engine)
"Is-a" (Car is-a Vehicle)
Coupling
Loosely Coupled
Tightly Coupled
Code Reusability
High
Moderate
Flexibility
More Flexible (can change components easily)
Less Flexible (inherited behavior is fixed)
Encapsulation
Strong (hides implementation details)
Weak (exposes superclass methods)
Code Maintainability
Easier
Harder (deep inheritance chains lead to complexity)
Multiple Behaviour
Can change behaviour at runtime
Fixed at compile time
Example
A Car
contains an Engine
A Car
extends Vehicle
When to Use Composition?
When we need code reuse without tight coupling.
When we need flexibility in changing object behaviour at runtime.
When inheritance doesn’t make sense (e.g., a
Car
is not anEngine
, but it has anEngine
).
Why Composition is Preferred?
More flexible than inheritance (allows dynamic behavior changes).
Encapsulates implementation details (avoids exposing unnecessary behavior).
Avoids tight coupling (can replace contained objects without breaking existing code).
Enhances code reuse (reusable independent components).
When to Use Inheritance?
When objects have a clear hierarchical relationship (
is-a
).When you need default behaviour sharing across multiple classes.
Code Example: Composition vs. Inheritance
Bad Example (Using Inheritance Incorrectly)
Problem: The Car
class is not really an Engine
, but it extends it, which breaks the "is-a" principle.
Good Example (Using Composition Correctly)
Better Design: Car
contains an Engine
but does not inherit from it. This keeps the code flexible and maintainable.
Last updated
Was this helpful?