2011-02-09 21 views
6

Gần đây chúng tôi đã thảo luận một khiếm khuyết mentioned here và một trong các bên nói một cái gì đó như "vâng, đó là lý do tại sao cuốn sách nói rằng thừa kế nên tránh.Trường hợp nào ý tưởng rằng "kế thừa là để tránh" bắt nguồn từ?

Tôi đã sử dụng thừa kế trong nhiều năm và nhận thấy nó rất hữu ích và tiện lợi Tôi cũng chắc chắn rằng người tranh cãi ít nhất là đã hiểu lầm những gì "những cuốn sách nói".

Có thực sự là một ý tưởng rằng thừa kế là loại xấu và nên tránh? và tôi có thể tìm hiểu thêm ở đâu?

+0

Vâng, tôi không biết nhưng tôi thích kế thừa bản thân mình. –

+0

@Tuzo: Có phải tất cả đều đun sôi thành "thành phần so với thừa kế" không? – sharptooth

+0

Ít nhất tôi nghĩ rằng đó là một phần quan trọng của nó (tất cả các câu trả lời đều đề cập đến nó). Mặc dù tôi phải thừa nhận rằng trí tuệ tôi thực sự yêu sự sang trọng khái niệm của thừa kế. ("Tại sao tôi không lấy nó !?" :)) –

Trả lời

9

Tôi nghĩ những gì anh ấy có thể có có nghĩa là thừa kế có thể bị lạm dụng, ngay cả trong trường hợp bố cục sẽ là giải pháp tốt hơn. Điều này được thảo luận trong một số sách, ví dụ:

Thừa kế là một cách mạnh mẽ để đạt được tái sử dụng mã, nhưng nó không phải luôn luôn công cụ tốt nhất cho công việc. Sử dụng không thích hợp, nó dẫn đến phần mềm mong manh. Nó là an toàn để sử dụng thừa kế trong một gói, trong đó lớp con và triển khai siêu lớp nằm dưới sự kiểm soát của cùng một lập trình viên. Cũng an toàn khi sử dụng thừa kế khi mở rộng các lớp học được thiết kế và tài liệu cụ thể cho tiện ích mở rộng (Mục 17). Thừa kế từ các lớp bê tông thông thường qua các ranh giới gói, tuy nhiên, rất nguy hiểm. Như một lời nhắc nhở, cuốn sách này sử dụng từ "kế thừa" để thừa kế thực hiện có nghĩa là (khi một lớp mở rộng khác). Các vấn đề được thảo luận trong mục này không áp dụng cho giao tiếp thừa kế (khi một lớp triển khai một giao diện hoặc nơi một giao diện mở rộng giao diện khác).

Không giống như lời gọi phương thức, di sản vi phạm gói gọn [Snyder86]. Nói cách khác, một phân lớp phụ thuộc vào các chi tiết thực hiện của siêu lớp của nó cho chức năng thích hợp của nó. Việc triển khai của lớp cha có thể thay đổi từ khi phát hành để phát hành và nếu có, lớp con có thể bị hỏng, ngay cả khi mã của nó không bị chạm vào . Kết quả là, một phân lớp phải phát triển song song với siêu lớp của nó, trừ khi tác giả của lớp cha đã thiết kế và ghi lại nó cụ thể là cho mục đích được mở rộng.

  • Effective C++ 3rd Edition có một số mặt hàng liên quan đến điều này:
    • mục 32: Đảm bảo mô hình thừa kế công cộng "là-a."
    • mục 34: Phân biệt giữa thừa kế của giao diện, thừa kế thực hiện
    • mục 38: Mô hình "has-a" hoặc "được triển khai thực hiện trong-terms-của" thông qua phần
+0

Xem thêm "Mẫu thiết kế đầu tiên". –

3

Không được tránh mọi lúc, nhưng nó cản trở sự linh hoạt bất cứ nơi nào bạn đang mắc kẹt với một tập hợp các hoạt động được xác định từ một lớp cha.Ý tưởng thiết kế cơ bản là "để thừa kế các bộ phận cố định và tiêm các bộ phận có thể thay đổi".

Trong Head First Desing Patterns có một ví dụ điển hình.

Giả sử bạn quyết định tạo mô hình vịt bằng lớp cơ sở triển khai fly(). Nói rằng bạn có một RubberDuck, người không thể bay, tất nhiên. Bạn ghi đè lên fly() bằng một phương thức không làm gì cả. Nhưng sau đó một số ngày bạn thêm DecoyDuck và quên ghi đè lên fly() và bạn nhận được một mớ hỗn độn. Nó sẽ là tốt hơn để xây dựng DecoyDuck tiêm các hành vi mong muốn (thành phần trên thừa kế).

+0

bạn có thể nói rằng vịt cao su là vịt vì nó không bay như vịt? nếu bạn có thể, là bay()) thực sự phù hợp để bao gồm trong lớp cơ sở vì nó không được chia sẻ bởi tất cả đó là vịt .... – Jean

+1

chính xác; thừa kế không phù hợp để giải quyết loại vấn đề này: nếu bạn nói "có, vịt cao su là vịt" bạn phải ghi đè lên fly() trong mọi phân lớp; nếu bạn nói "không", bạn phải sao chép nó ở mọi nơi –

+0

Tôi đồng ý với bạn về nguyên tắc nhưng tôi thấy ví dụ ít thuyết phục hơn. Tôi nghĩ vấn đề là sự trừu tượng của RubberDuck không chính xác. Nếu bạn nhìn vào một con vịt và một con vịt cao su và cố gắng phân loại chúng, hầu hết mọi người sẽ nói rằng một con vịt là một con vật (hoặc chim) trong khi một con vịt cao su là một đồ chơi * trông giống như một con vịt. –

2

Không được thừa kế thừa kế 'nguyên trạng'.
Thừa kế nên được sử dụng (và chỉ được sử dụng) khi bạn muốn xác định/mô tả mối quan hệ 'là một'.

Khi một thực thể 'không phải là' sự khác biệt, thực thể không được kế thừa từ sự khác biệt. Trong những trường hợp như vậy, bố cục nên được sử dụng.

2

Thừa kế giúp tổng quát hóa (được upcasting trong điều khoản OOP), trong khi Thành phần giúp định nghĩa hành vi (Inversion of Control - hoặc Dependency Injection).

Người ta nên sử dụng bất kỳ quyền nào mang lại nhiều lợi ích hơn; nhưng ưu tiên Thành phần cũng làm cho mã mở rộng hơn. Vì vậy, mã sẽ trở thành "đóng cửa để sửa đổi, nhưng mở để mở rộng" và do đó "HAS-A là tốt hơn so với IS-A".

Giống như là một chiếc xe hơi của mình hoặc sở hữu một chiếc xe hơi (hay không?)

Các vấn đề liên quan