Tôi có một lớp cơ sở Base,. Nó có hai lớp con, Sub1và Sub2. Mỗi lớp con có một số phương thức bổ sung. Ví dụ, Sub1có Sandwich makeASandwich(Ingredients... ingredients), và Sub2có boolean contactAliens(Frequency onFrequency).
Vì các phương thức này có các tham số khác nhau và thực hiện những điều hoàn toàn khác nhau, nên chúng hoàn toàn không tương thích và tôi không thể chỉ sử dụng đa hình để giải quyết vấn đề này.
Basecung cấp hầu hết các chức năng và tôi có một bộ sưu tập lớn các Baseđối tượng. Tuy nhiên, tất cả Basecác đối tượng là a Sub1hoặc a Sub2, và đôi khi tôi cần biết chúng là gì.
Có vẻ như một ý tưởng tồi để làm như sau:
for (Base base : bases) {
if (base instanceof Sub1) {
((Sub1) base).makeASandwich(getRandomIngredients());
// ... etc.
} else { // must be Sub2
((Sub2) base).contactAliens(getFrequency());
// ... etc.
}
}
Vì vậy, tôi đã đưa ra một chiến lược để tránh điều này mà không cần đúc. Basebây giờ có các phương thức sau:
boolean isSub1();
Sub1 asSub1();
Sub2 asSub2();
Và tất nhiên, Sub1thực hiện các phương pháp này như
boolean isSub1() { return true; }
Sub1 asSub1(); { return this; }
Sub2 asSub2(); { throw new IllegalStateException(); }
Và Sub2thực hiện chúng theo cách ngược lại.
Thật không may, bây giờ Sub1và Sub2có các phương thức này trong API riêng của họ. Vì vậy, tôi có thể làm điều này, ví dụ, trên Sub1.
/** no need to use this if object is known to be Sub1 */
@Deprecated
boolean isSub1() { return true; }
/** no need to use this if object is known to be Sub1 */
@Deprecated
Sub1 asSub1(); { return this; }
/** no need to use this if object is known to be Sub1 */
@Deprecated
Sub2 asSub2(); { throw new IllegalStateException(); }
Theo cách này, nếu đối tượng chỉ được biết là a Base, các phương thức này không bị phản đối và có thể được sử dụng để "tự" chuyển sang một loại khác để tôi có thể gọi các phương thức của lớp con trên nó. Theo một cách nào đó, điều này có vẻ thanh lịch đối với tôi, nhưng mặt khác, tôi lại lạm dụng các chú thích không được chấp nhận như một cách để "loại bỏ" các phương thức khỏi một lớp.
Vì một Sub1thể hiện thực sự là một Base, nên sử dụng tính kế thừa thay vì đóng gói. Là những gì tôi đang làm tốt? Có cách nào tốt hơn để giải quyết vấn đề này?
instanceof, theo cách đòi hỏi nhiều thao tác gõ, dễ bị lỗi và khiến cho việc thêm nhiều lớp con trở nên khó khăn hơn.
Sub1và Sub2không thể được sử dụng thay thế cho nhau, thì tại sao bạn lại đối xử với chúng như vậy? Tại sao không theo dõi riêng các 'nhà sản xuất bánh sandwich' và 'người tiếp xúc với người ngoài hành tinh' của bạn?