1.3 Inheritance & Composition
← Back to Chapter 1: OOPs Concepts
Software architecture relies heavily on structured relationships between components. Java supports two primary modeling mechanisms: Inheritance (IS-A) and Composition (HAS-A).
1. Inheritance (IS-A Relationship)
Inheritance allows a subclass to acquire fields and methods of a parent superclass using the extends keyword:
public class Employee {
protected final String id;
protected final String name;
public Employee(String id, String name) {
this.id = id;
this.name = name;
}
public double calculatePay() {
return 3000.0;
}
}
public class Manager extends Employee {
private final double bonus;
public Manager(String id, String name, double bonus) {
super(id, name); // 1. Must invoke super constructor first
this.bonus = bonus;
}
@Override
public double calculatePay() {
return super.calculatePay() + bonus; // 2. Delegate to superclass implementation
}
}
Key Inheritance Constraints in Java
- Single Class Inheritance: Java does not support multiple class inheritance (
class A extends B, Cis illegal) to avoid the "Diamond Problem". ObjectSuperclass: All Java classes directly or indirectly inherit fromjava.lang.Object.finalClasses: Classes markedfinal(likejava.lang.String) cannot be extended.
2. Composition (HAS-A Relationship)
Composition builds complex types by assembling smaller, independent components rather than inheriting behavior:
public class DatabaseConnectionPool {
public void executeQuery(String sql) { /* ... */ }
}
public class UserRepository {
// HAS-A relationship: UserRepository is NOT a ConnectionPool
private final DatabaseConnectionPool pool;
public UserRepository(DatabaseConnectionPool pool) {
this.pool = pool;
}
public void findUser(long id) {
pool.executeQuery("SELECT * FROM users WHERE id = " + id);
}
}
3. "Favor Composition over Inheritance"
The Gang of Four (GoF) design principle recommends composition over class inheritance:
| Factor | Inheritance (IS-A) | Composition (HAS-A) |
|---|---|---|
| Coupling | Tight coupling: Changes to superclass ripple down into subclasses | Loose coupling: Components interact purely via interfaces |
| Encapsulation | Superclass implementation details leak into child classes | Black-box reuse: Internal state remains private |
| Flexibility | Fixed at compile-time (cannot change parent class dynamically) | Swappable at runtime via Dependency Injection (Spring IoC) |
| Testing | Difficult to mock deep inheritance hierarchies | Effortless to inject mock dependencies in unit tests |