Benim bir temel sınıfım var Base
. İki alt sınıfı var Sub1
ve Sub2
. Her alt sınıfın bazı ek yöntemleri vardır. Örneğin, Sub1
yer alır Sandwich makeASandwich(Ingredients... ingredients)
, ve Sub2
yer alır boolean contactAliens(Frequency onFrequency)
.
Bu yöntemler farklı parametreler alıp tamamen farklı şeyler yaptıkları için tamamen uyumsuzlar ve bu sorunu çözmek için sadece polimorfizm kullanamıyorum.
Base
İşlevlerin çoğunu sağlar ve geniş bir Base
nesne koleksiyonuna sahibim . Ancak, tüm Base
nesneler ya a Sub1
ya da Sub2
a'dır ve bazen onların ne olduğunu bilmem gerekir.
Aşağıdakileri yapmak kötü bir fikir gibi görünüyor:
for (Base base : bases) {
if (base instanceof Sub1) {
((Sub1) base).makeASandwich(getRandomIngredients());
// ... etc.
} else { // must be Sub2
((Sub2) base).contactAliens(getFrequency());
// ... etc.
}
}
Bu yüzden oyuncu seçmeden bunu önlemek için bir strateji ile geldi. Base
şimdi bu yöntemlere sahip:
boolean isSub1();
Sub1 asSub1();
Sub2 asSub2();
Ve tabii ki, Sub1
bu yöntemleri uygular.
boolean isSub1() { return true; }
Sub1 asSub1(); { return this; }
Sub2 asSub2(); { throw new IllegalStateException(); }
Ve Sub2
onları tam tersi şekilde uygular.
Ne yazık ki, şimdi Sub1
ve Sub2
bu yöntemleri kendi API'lerinde bulundurun. Böylece, örneğin bunu yapabilirim 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(); }
Bu şekilde, eğer nesne sadece a olarak bilinirse Base
, bu yöntemler kullanımdan kaldırılmıştır ve alt sınıfın metotlarını çağırmak için kendisini farklı bir türe dökmek için kullanılabilir. Bu bana bir şekilde zarif görünüyor, ancak diğer taraftan, bir sınıftaki yöntemleri “kaldırmanın” bir yolu olarak kullanımdan kaldırılmış açıklamaları kötüye kullanıyorum.
Bir Sub1
örnek gerçekten bir Temel olduğu için , kapsülleme yerine kalıtımı kullanmak mantıklıdır. İyi yaptığım şey mi? Bu sorunu çözmenin daha iyi bir yolu var mı?
instanceof
çok fazla yazmaya ihtiyaç duyan bir şekilde hataya açık ve daha fazla alt sınıf eklemeyi zorlaştırıyorsunuz.
Sub1
ve Sub2
birbirlerinin yerine kullanılamazlar, o zaman neden bunları özel olarak muamele yapmak? Neden 'sandviç üreticileri' ve 'yabancı-temasçılar'ı ayrı ayrı takip etmiyorsunuz?