Tôi có một lớp cơ sở Base
,. Nó có hai lớp con, Sub1
và Sub2
. Mỗi lớp con có một số phương thức bổ sung. Ví dụ, Sub1
có Sandwich makeASandwich(Ingredients... ingredients)
, và Sub2
có 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.
Base
cung 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ả Base
các đối tượng là a Sub1
hoặ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. Base
bây giờ có các phương thức sau:
boolean isSub1();
Sub1 asSub1();
Sub2 asSub2();
Và tất nhiên, Sub1
thự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à Sub2
thực hiện chúng theo cách ngược lại.
Thật không may, bây giờ Sub1
và Sub2
có 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 Sub1
thể 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.
Sub1
và Sub2
khô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?