ist eine Beziehung vom Typ — modelliert mit ( ). ist eine Beziehung vom Typ — modelliert mit ( ). Die richtige Wahl zu treffen ist eine grundlegende Modellierungsentscheidung.
ist eine Beziehung vom Typ — modelliert mit ( ). ist eine Beziehung vom Typ — modelliert mit ( ). Die richtige Wahl zu treffen ist eine grundlegende Modellierungsentscheidung.
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
}
Fragen Sie: "Ist X eine Art von Y, oder hat X ein/benutzt 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) ✅
Menschen greifen auf Vererbung zurück, um Code wiederzuverwenden, auch wenn die Beziehung wirklich has-a ist. Wenn Sie die Unterklasse nicht überall durch die Basisklasse ersetzen könnten, ist es wahrscheinlich nicht is-a — verwenden Sie Komposition.
Dieser Unterschied ist die praktische Entscheidungsregel hinter "Komposition gegenüber Vererbung bevorzugen": wählen Sie die Beziehung, die wahr ist, nicht die, die ein paar Zeilen spart.
Wenn Sie es richtig machen, bleiben Hierarchien flach und ehrlich, und es verhindert Liskov-Verletzungen, bei denen ein "Subtyp" seinen übergeordneten Typ nicht wirklich vertreten kann.