Bạn đã có một vài câu trả lời hay, nhưng con voi to lớn trong phòng trong câu hỏi của bạn là câu này:
nghe được từ ai đó rằng phải sử dụng kế thừa phải tránh và thay vào đó chúng ta nên sử dụng giao diện
Như một quy tắc của ngón tay cái, khi ai đó đưa cho bạn một quy tắc của ngón tay cái, sau đó bỏ qua nó. Điều này không chỉ dành cho "ai đó nói với bạn điều gì đó", mà còn để đọc nội dung trên internet. Trừ khi bạn biết tại sao (và thực sự có thể đứng đằng sau nó), những lời khuyên như vậy là vô giá trị và thường rất có hại.
Theo kinh nghiệm của tôi, các khái niệm quan trọng và hữu ích nhất trong OOP là "khớp nối thấp" và "độ gắn kết cao" (các lớp / đối tượng biết càng ít càng tốt về nhau và mỗi đơn vị chịu trách nhiệm về càng ít điều càng tốt).
Khớp nối thấp
Điều này có nghĩa là bất kỳ "gói nội dung" nào trong mã của bạn nên phụ thuộc vào môi trường xung quanh càng ít càng tốt. Điều này áp dụng cho các lớp (thiết kế lớp) nhưng cũng có các đối tượng (triển khai thực tế), "tệp" nói chung (nghĩa là số #include
s trên mỗi .cpp
tệp đơn , số lượng import
trên mỗi .java
tệp đơn , v.v.).
Một dấu hiệu cho thấy hai thực thể được ghép nối là một trong số chúng sẽ bị phá vỡ (hoặc cần phải thay đổi) khi cái kia bị thay đổi theo bất kỳ cách nào.
Kế thừa tăng khớp nối, rõ ràng; thay đổi lớp cơ sở thay đổi tất cả các lớp con.
Các giao diện giảm khớp nối: bằng cách xác định hợp đồng rõ ràng, dựa trên phương pháp, bạn có thể tự do thay đổi mọi thứ về cả hai mặt của giao diện, miễn là bạn không thay đổi hợp đồng. (Lưu ý rằng "giao diện" là một khái niệm chung, các interface
lớp trừu tượng Java hoặc C ++ chỉ là chi tiết triển khai).
Độ kết dính cao
Điều này có nghĩa là để mỗi lớp, đối tượng, tệp, vv được quan tâm hoặc chịu trách nhiệm ít nhất có thể. Tức là tránh các lớp học lớn làm nhiều thứ. Trong ví dụ của bạn, nếu vũ khí của bạn có các khía cạnh hoàn toàn riêng biệt (đạn, hành vi bắn, biểu diễn đồ họa, biểu diễn kho, v.v.), thì bạn có thể có các lớp khác nhau đại diện chính xác cho một trong những điều đó. Lớp vũ khí chính sau đó biến thành "người nắm giữ" những chi tiết đó; một đối tượng vũ khí sau đó ít hơn một vài gợi ý đến những chi tiết đó.
Trong ví dụ này, bạn sẽ đảm bảo rằng lớp của bạn đại diện cho "Hành vi bắn" biết ít nhất có thể về con người về lớp vũ khí chính. Tối ưu, không có gì cả. Chẳng hạn, điều này có nghĩa là bạn có thể đưa ra "Hành vi bắn" cho bất kỳ đối tượng nào trong thế giới của bạn (tháp pháo, núi lửa, NPC ...) chỉ bằng một cái búng tay. Nếu đôi lúc bạn muốn thay đổi cách thể hiện vũ khí trong kho, thì bạn chỉ có thể làm như vậy - chỉ có lớp kho của bạn biết về điều đó.
Một dấu hiệu cho thấy một thực thể không gắn kết là nếu nó phát triển ngày càng lớn hơn, phân nhánh theo nhiều hướng cùng một lúc.
Kế thừa như bạn mô tả nó làm giảm sự gắn kết - các lớp vũ khí của bạn, vào cuối ngày, những khối lớn xử lý tất cả các khía cạnh khác nhau, không liên quan đến vũ khí của bạn.
Các giao diện gián tiếp tăng sự gắn kết bằng cách phân chia rõ ràng trách nhiệm giữa hai bên của giao diện.
làm gì bây giờ
Vẫn không có quy tắc cứng và nhanh, tất cả những điều này chỉ là hướng dẫn. Nói chung, như người dùng TKK đã đề cập trong câu trả lời của mình, kế thừa được dạy rất nhiều trong trường học và sách; đó là những thứ lạ mắt về OOP. Các giao diện có lẽ nhàm chán hơn để dạy, và cũng (nếu bạn đi qua các ví dụ tầm thường) khó hơn một chút, mở ra lĩnh vực tiêm phụ thuộc, không quá rõ ràng như thừa kế.
Vào cuối ngày, chương trình dựa trên thừa kế của bạn vẫn tốt hơn là không có thiết kế OOP rõ ràng nào cả. Vì vậy, cảm thấy tự do để gắn bó với nó. Nếu bạn muốn, bạn có thể suy nghĩ lại / google một chút về Kết nối thấp, Độ kết dính cao và xem liệu bạn có muốn thêm kiểu suy nghĩ đó vào kho vũ khí của mình không. Bạn luôn có thể cấu trúc lại để thử nó nếu bạn muốn, sau này; hoặc thử các cách tiếp cận dựa trên giao diện trên mô-đun mã mới lớn hơn tiếp theo của bạn.