Is-a هي علاقة من نوع type — يتم نمذجتها باستخدام inheritance ( ). هي علاقة من نوع — يتم نمذجتها باستخدام ( ). اختيار العلاقة الصحيحة هو قرار نمذجة أساسي.
Is-a هي علاقة من نوع type — يتم نمذجتها باستخدام inheritance ( ). هي علاقة من نوع — يتم نمذجتها باستخدام ( ). اختيار العلاقة الصحيحة هو قرار نمذجة أساسي.
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 — استخدم composition.
هذا التمييز هو قاعدة القرار العملية خلف "favor composition over inheritance": اختر العلاقة التي تكون صحيحة، وليس العلاقة التي توفر بعض الأسطر من الكود.
الحصول على الاختيار الصحيح يحافظ على التسلسلات الهرمية ضحلة وصادقة، ويمنع انتهاكات Liskov حيث لا يمكن لـ "subtype" أن تقف فعلاً مكان والدها.