is een relatie van — gemodelleerd met (een ). is een relatie van — gemodelleerd met (een ). Het kiezen van het juiste is een kernbeslissing bij modellering.
is een relatie van — gemodelleerd met (een ). is een relatie van — gemodelleerd met (een ). Het kiezen van het juiste is een kernbeslissing bij modellering.
CarVehicleCarEngine// IS-A → inheritance
class Vehicle { void move() {} }
class Car extends Vehicle { } // a Car IS A Vehicle
// HAS-A → composition
class Engine { void start() {} }
class Car2 {
private Engine engine = new Engine(); // a Car HAS AN Engine
void start() { engine.start(); } // delegate to the part
}
Stel jezelf de vraag: "Is X een soort van Y, of heeft X een Y?"
A Dog IS-A Animal → inheritance ✅
A Car HAS-A Engine → composition ✅
A Square IS-A Shape → inheritance ✅
A Manager HAS Employees → composition (a list) ✅
A Stack HAS-A list (not IS-A) → composition (see earlier pitfall) ✅
Mensen grijpen naar inheritance om code te hergebruiken, zelfs wanneer de relatie eigenlijk has-a is. Als je de subclass nooit voor de base kunt gebruiken, is het waarschijnlijk geen is-a — gebruik composition.
Deze onderscheiding is de praktische beslissingsregel achter "geef composition de voorkeur boven inheritance": kies de relatie die waar is, niet degene die een paar regels bespaart.
Het goed doen houdt hiërarchieën ondiep en eerlijk, en voorkomt Liskov-schendingen waarbij een "subtype" niet echt voor zijn parent kan staan.