là quan hệ về — được mô hình hóa bằng (một ). là quan hệ về — được mô hình hóa bằng (một ). Chọn đúng quan hệ là một quyết định mô hình hóa cốt lõi.
là quan hệ về — được mô hình hóa bằng (một ). là quan hệ về — được mô hình hóa bằng (một ). Chọn đúng quan hệ là một quyết định mô hình hóa cốt lõi.
CarVehicleCarEngine// IS-A → inheritance
class Vehicle { void move() {} }
class Car extends Vehicle { } // một Car LÀ MỘT Vehicle
// HAS-A → composition
class Engine { void start() {} }
class Car2 {
private Engine engine = new Engine(); // một Car CÓ MỘT Engine
void start() { engine.start(); } // ủy thác cho bộ phận
}
Hãy hỏi: "X là một loại của Y, hay X có/dùng một Y?"
Một Dog IS-A Animal → inheritance ✅
Một Car HAS-A Engine → composition ✅
Một Square IS-A Shape → inheritance ✅
Một Manager CÓ Employees → composition (một list) ✅
Một Stack HAS-A list (không IS-A) → composition (xem cạm bẫy trước đó) ✅
Mọi người thường với tới inheritance để tái sử dụng code, ngay cả khi quan hệ thực ra là has-a. Nếu bạn không bao giờ thay thế subclass cho base ở mọi nơi, thì có lẽ đó không phải is-a — hãy dùng composition.
Phân biệt này là quy tắc quyết định thực dụng đằng sau "ưu tiên composition hơn inheritance": chọn quan hệ nào đúng, không phải quan hệ tiết kiệm vài dòng code.
Làm đúng giúp giữ các cây phân cấp nông và trung thực, và nó ngăn các vi phạm Liskov nơi một "subtype" thực ra không thể đứng thay cho cha của nó.