Một thiếu sót nổi tiếng của hệ thống phân cấp lớp truyền thống là chúng rất tệ khi mô hình hóa thế giới thực. Ví dụ, cố gắng đại diện cho các loài động vật với các lớp. Thực tế có một số vấn đề khi làm điều đó, nhưng một vấn đề mà tôi chưa bao giờ thấy giải pháp là khi một lớp con "mất" một hành vi hoặc tài sản được xác định trong một siêu hạng, giống như một con chim cánh cụt không thể bay (ở đó có lẽ là những ví dụ tốt hơn, nhưng đó là ví dụ đầu tiên xuất hiện trong đầu tôi).
Một mặt, bạn không muốn xác định, đối với mọi thuộc tính và hành vi, một số cờ chỉ định nếu nó có ở tất cả và kiểm tra nó mỗi lần trước khi truy cập vào hành vi hoặc tài sản đó. Bạn chỉ muốn nói rằng chim có thể bay, đơn giản và rõ ràng, trong lớp Chim. Nhưng sau đó, thật tuyệt nếu người ta có thể định nghĩa "ngoại lệ" sau đó, mà không phải sử dụng một số hack khủng khiếp ở khắp mọi nơi. Điều này thường xảy ra khi một hệ thống đã hoạt động được một thời gian. Bạn đột nhiên tìm thấy một "ngoại lệ" hoàn toàn không phù hợp với thiết kế ban đầu và bạn không muốn thay đổi một phần lớn mã của mình để phù hợp với nó.
Vì vậy, có một số ngôn ngữ hoặc mẫu thiết kế có thể xử lý vấn đề này một cách sạch sẽ, mà không yêu cầu thay đổi lớn đối với "siêu hạng" và tất cả các mã sử dụng nó? Ngay cả khi một giải pháp chỉ xử lý một trường hợp cụ thể, một số giải pháp có thể cùng nhau tạo thành một chiến lược hoàn chỉnh.
Sau khi suy nghĩ nhiều hơn, tôi nhận ra mình đã quên Nguyên tắc thay thế Liskov. Đó là lý do tại sao bạn không thể làm điều đó. Giả sử bạn xác định "đặc điểm / giao diện" cho tất cả các "nhóm tính năng" chính, bạn có thể tự do triển khai các đặc điểm trong các nhánh khác nhau của hệ thống phân cấp, như đặc điểm Bay có thể được thực hiện bởi Chim và một số loại sóc và cá đặc biệt.
Vì vậy, câu hỏi của tôi có thể lên tới "Làm thế nào tôi có thể không thực hiện một đặc điểm?" Nếu siêu hạng của bạn là một Tuần tự hóa Java, bạn cũng phải là một, ngay cả khi không có cách nào để bạn tuần tự hóa trạng thái của mình, ví dụ nếu bạn có chứa "Ổ cắm".
Một cách để làm điều đó là luôn xác định tất cả các đặc điểm của bạn theo cặp ngay từ đầu: Bay và Không theo dõi (sẽ ném UnsupportedOperationException, nếu không được kiểm tra). Không đặc điểm sẽ không xác định bất kỳ giao diện mới nào và có thể được kiểm tra đơn giản. Âm thanh như một giải pháp "giá rẻ", đặc biệt nếu được sử dụng từ đầu.
" it would be nice if one could define "exceptions" afterward, without having to use some horrible hacks everywhere"
bạn có xem xét một phương pháp nhà máy kiểm soát hành vi hacky không?
NotSupportedException
từ Penguin.fly()
.
class Penguin < Bird; undef fly; end;
. Cho dù bạn nên là một câu hỏi khác.
function save_yourself_from_crashing_airplane(Bird b) { f.fly() }
sẽ phức tạp hơn rất nhiều. (như Peter Török đã nói, nó vi phạm LSP)