Tôi tin rằng lý do thực sự khiến nhiều người cảm thấy các lớp nên final
/ sealed
là hầu hết các lớp mở rộng không trừu tượng không được ghi lại đúng cách .
Hãy để tôi giải thích. Bắt đầu từ xa, có một quan điểm trong số một số lập trình viên rằng sự kế thừa như một công cụ trong OOP bị lạm dụng và lạm dụng rộng rãi. Tất cả chúng ta đều đã đọc nguyên tắc thay thế Liskov, mặc dù điều này không ngăn chúng ta vi phạm nó hàng trăm (thậm chí hàng ngàn) lần.
Điều này là các lập trình viên thích sử dụng lại mã. Ngay cả khi nó không phải là một ý tưởng tốt. Và kế thừa là một công cụ quan trọng trong "reabusing" mã này. Quay lại câu hỏi cuối cùng / niêm phong.
Tài liệu phù hợp cho một lớp cuối cùng / niêm phong là tương đối nhỏ: bạn mô tả mỗi phương thức làm gì, các đối số, giá trị trả về, v.v ... Tất cả các công cụ thông thường.
Tuy nhiên, khi bạn viết tài liệu đúng về một lớp có thể mở rộng, bạn phải bao gồm ít nhất những điều sau đây :
- Sự phụ thuộc giữa các phương thức (phương thức nào gọi, v.v.)
- Phụ thuộc vào các biến cục bộ
- Hợp đồng nội bộ mà lớp mở rộng nên tôn vinh
- Quy ước cuộc gọi cho mỗi phương thức (ví dụ: Khi bạn ghi đè lên nó, bạn có gọi lệnh
super
thực hiện không? Bạn có gọi nó ở đầu phương thức hay cuối cùng không? Hãy nghĩ hàm tạo so với hàm hủy)
- ...
Đây chỉ là trên đỉnh đầu của tôi. Và tôi có thể cung cấp cho bạn một ví dụ về lý do tại sao mỗi trong số này là quan trọng và bỏ qua nó sẽ làm hỏng một lớp mở rộng.
Bây giờ, hãy xem xét bao nhiêu nỗ lực tài liệu nên đi vào tài liệu đúng từng điều này. Tôi tin rằng một lớp học có 7-8 phương thức (có thể quá nhiều trong một thế giới lý tưởng hóa, nhưng quá ít trong thực tế) cũng có thể có một tài liệu khoảng 5 trang, chỉ có văn bản. Vì vậy, thay vào đó, chúng tôi tránh ra giữa chừng và không niêm phong lớp học, để những người khác có thể sử dụng nó, nhưng cũng không ghi chép đúng, vì nó sẽ mất một lượng thời gian khổng lồ (và, bạn biết đấy, nó có thể Dù sao cũng không bao giờ được gia hạn, vậy tại sao phải bận tâm?).
Nếu bạn đang thiết kế một lớp học, bạn có thể cảm thấy sự cám dỗ để niêm phong nó để mọi người không thể sử dụng nó theo cách mà bạn không lường trước được (và chuẩn bị cho). Mặt khác, khi bạn đang sử dụng mã của người khác, đôi khi từ API công khai không có lý do rõ ràng nào cho lớp là cuối cùng và bạn có thể nghĩ "Chết tiệt, điều này chỉ khiến tôi mất 30 phút để tìm cách giải quyết".
Tôi nghĩ rằng một số yếu tố của một giải pháp là:
- Đầu tiên để đảm bảo mở rộng là một ý tưởng hay khi bạn là khách hàng của mã và để thực sự ủng hộ thành phần hơn kế thừa.
- Thứ hai để đọc toàn bộ hướng dẫn sử dụng (một lần nữa với tư cách là khách hàng) để đảm bảo bạn không nhìn thấy thứ gì đó được đề cập.
- Thứ ba, khi bạn đang viết một đoạn mã khách hàng sẽ sử dụng, hãy viết tài liệu phù hợp cho mã (vâng, đường dài). Một ví dụ tích cực, tôi có thể cung cấp tài liệu iOS của Apple. Chúng không đủ để người dùng luôn mở rộng đúng các lớp của mình, nhưng ít nhất chúng bao gồm một số thông tin về thừa kế. Đó là nhiều hơn tôi có thể nói cho hầu hết các API.
- Thứ tư, thực sự cố gắng mở rộng lớp học của riêng bạn, để đảm bảo nó hoạt động. Tôi là một người ủng hộ lớn bao gồm nhiều mẫu và thử nghiệm trong API và khi bạn thực hiện thử nghiệm, bạn cũng có thể kiểm tra chuỗi thừa kế: sau tất cả chúng là một phần trong hợp đồng của bạn!
- Thứ năm, trong các tình huống khi bạn nghi ngờ, chỉ ra rằng lớp học không có nghĩa là được mở rộng và thực hiện nó là một ý tưởng tồi (tm). Cho biết bạn không nên chịu trách nhiệm cho việc sử dụng ngoài ý muốn như vậy, nhưng vẫn không niêm phong lớp học. Rõ ràng, điều này không bao gồm các trường hợp khi lớp nên được niêm phong 100%.
- Cuối cùng, khi niêm phong một lớp, cung cấp một giao diện như một móc trung gian, để khách hàng có thể "viết lại" phiên bản sửa đổi của lớp mình và làm việc xung quanh lớp 'niêm phong' của bạn. Bằng cách này, anh ta có thể thay thế lớp niêm phong bằng việc thực hiện của mình. Bây giờ, điều này là rõ ràng, vì nó là khớp nối lỏng lẻo ở dạng đơn giản nhất của nó, nhưng nó vẫn đáng được đề cập.
Cũng đáng để đề cập đến câu hỏi "triết học" sau đây: Liệu một lớp là sealed
/ final
một phần của hợp đồng cho lớp học, hay một chi tiết thực hiện? Bây giờ tôi không muốn bước đi ở đó, nhưng một câu trả lời cho điều này cũng sẽ ảnh hưởng đến quyết định của bạn có nên niêm phong một lớp học hay không.
Open/Closed principle
, chứ không phảiClosed Principle.