9 · 32 · 5 min
Inheritance, and when it is the wrong tool
Inheritance lets a class take another's fields and methods and add to them.
class Vehicle {
protected int wheels;
void start() { System.out.println("starting"); }
}
class Car extends Vehicle {
Car() { wheels = 4; }
void openBoot() { }
}Car gets wheels and start without copying them, and adds its own.
The test that matters
Inheritance means is a. A car is a vehicle, so it fits.
Composition means has a. A car has an engine. Writing class Car extends Engine would be absurd, and yet the equivalent mistake is made constantly with less obvious pairs.
class Stack extends ArrayList { } // wrong: a stack is not a list
class Stack { private List items; } // right: a stack HAS a listThe first is wrong because ArrayList has get(5) and add(0, x), and a stack that lets you reach into the middle is not a stack. Inheritance gave it methods that break its own rules.
Prefer composition
Inheritance is the strongest coupling in the language. The subclass depends on the parent's fields, methods and behaviour, and a change to the parent can break every subclass at once. This is the fragile base class problem.
Composition is looser: the class holds a reference, uses the methods it wants, and exposes nothing it did not choose to.