Theo yêu cầu của exizt, tôi đang mở rộng bình luận của mình thành một câu trả lời dài hơn.
Sai lầm lớn nhất mà mọi người mắc phải là tin rằng các giao diện chỉ đơn giản là các lớp trừu tượng trống rỗng. Giao diện là cách để một lập trình viên nói, "Tôi không quan tâm những gì bạn đưa cho tôi, miễn là nó tuân theo quy ước này."
Thư viện .NET phục vụ như một ví dụ tuyệt vời. Ví dụ: khi bạn viết một hàm chấp nhận một IEnumerable<T>
, điều bạn đang nói là: "Tôi không quan tâm đến việc bạn đang lưu trữ dữ liệu của mình như thế nào . Tôi chỉ muốn biết rằng tôi có thể sử dụng một foreach
vòng lặp.
Điều này dẫn đến một số mã rất linh hoạt. Đột nhiên để được tích hợp, tất cả những gì bạn cần làm là chơi theo các quy tắc của các giao diện hiện có. Nếu việc thực hiện giao diện khó khăn hoặc khó hiểu, thì có lẽ đó là một gợi ý rằng bạn đang cố gắng đẩy một chốt vuông vào một lỗ tròn.
Nhưng sau đó, câu hỏi được đặt ra: "Thế còn việc sử dụng lại mã? Các giáo sư CS của tôi nói với tôi rằng thừa kế là giải pháp cho tất cả các vấn đề tái sử dụng mã và sự thừa kế đó cho phép bạn viết một lần và sử dụng ở mọi nơi và nó sẽ chữa khỏi bệnh viêm màng não trong quá trình giải cứu trẻ mồ côi. từ những vùng biển đang trỗi dậy và sẽ không còn nước mắt nữa và v.v. v.v. "
Sử dụng tính kế thừa chỉ vì bạn thích âm thanh của từ "tái sử dụng mã" là một ý tưởng khá tồi. Các hướng dẫn đang styling bởi Google làm cho thời điểm này khá ngắn gọn:
Thành phần thường thích hợp hơn thừa kế. ... [B] vì mã thực hiện một lớp con được trải rộng giữa lớp cơ sở và lớp con, việc hiểu một triển khai có thể khó khăn hơn. Lớp con không thể ghi đè các hàm không ảo, vì vậy lớp con không thể thay đổi việc thực hiện.
Để minh họa tại sao sự kế thừa không phải lúc nào cũng là câu trả lời, tôi sẽ sử dụng một lớp có tên MyecialFileWriter. Một người mù quáng tin rằng thừa kế là giải pháp cho tất cả các vấn đề sẽ lập luận rằng bạn nên cố gắng kế thừa từ đó FileStream
, kẻo bạn sẽ sao chép FileStream
mã của mình. Người thông minh nhận ra rằng điều này là ngu ngốc. Bạn chỉ nên có một FileStream
đối tượng trong lớp của mình (dưới dạng biến cục bộ hoặc biến thành viên) và sử dụng chức năng của nó.
Các FileStream
ví dụ có vẻ giả tạo, nhưng nó không phải. Nếu bạn có hai lớp mà cả hai thực hiện cùng một giao diện theo cùng một cách chính xác, thì bạn nên có một lớp thứ ba gói gọn mọi hoạt động được sao chép. Mục tiêu của bạn là viết các lớp là các khối có thể tái sử dụng khép kín, có thể ghép lại với nhau như các bản legos.
Điều này không có nghĩa là nên tránh việc thừa kế bằng mọi giá. Có nhiều điểm để xem xét, và hầu hết sẽ được đề cập bằng cách nghiên cứu câu hỏi, "Thành phần so với Kế thừa". Stack Overflow rất riêng của chúng tôi có một vài câu trả lời hay về chủ đề này.
Vào cuối ngày, tình cảm đồng nghiệp của bạn thiếu chiều sâu hoặc sự hiểu biết cần thiết để đưa ra quyết định sáng suốt. Nghiên cứu chủ đề và tìm ra nó cho chính mình.
Khi minh họa sự kế thừa, mọi người đều sử dụng động vật. Điều đó là vô ích. Trong 11 năm phát triển, tôi chưa bao giờ viết một lớp có tên Cat
, vì vậy tôi sẽ không sử dụng nó làm ví dụ.
alligator
eat
Tất nhiên, việc thực hiện khác nhau ở chỗ nó chấp nhậncat
vàdog
làm tham số.