είναι μια σχέση τύπου — μοντελοποιημένη με ( ). είναι μια σχέση τύπου — μοντελοποιημένη με ( ). Η επιλογή της σωστής είναι μια βασική απόφαση μοντελοποίησης.
είναι μια σχέση τύπου — μοντελοποιημένη με ( ). είναι μια σχέση τύπου — μοντελοποιημένη με ( ). Η επιλογή της σωστής είναι μια βασική απόφαση μοντελοποίησης.
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
}
Ερωτήστε: "Είναι το X ένα είδος Y, ή το X έχει/χρησιμοποιεί ένα 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) ✅
Οι άνθρωποι καταφεύγουν στην κληρονομικότητα για επαναχρησιμοποίηση κώδικα, ακόμη και όταν η σχέση είναι πραγματικά has-a. Αν δεν θα μπορούσατε ποτέ να αντικαταστήσετε την υποκλάση με τη βάση παντού, είναι πιθανώς όχι is-a — χρησιμοποιήστε σύνθεση.
Αυτή η διάκριση είναι ο πρακτικός κανόνας απόφασης πίσω από "προτιμάτε τη σύνθεση έναντι της κληρονομικότητας": επιλέξτε τη σχέση που είναι αληθινή, όχι αυτή που εξοικονομεί μερικές γραμμές.
Η σωστή επιλογή διατηρεί τις ιεραρχίες ρηχές και ειλικρινείς, και αποτρέπει παραβιάσεις Liskov όπου ένα "υποτύπος" δεν μπορεί στην πραγματικότητα να αντικαταστήσει τον γονέα του.