Eu tenho uma classe base Base,. Tem duas subclasses Sub1e Sub2. Cada subclasse possui alguns métodos adicionais. Por exemplo, Sub1tem Sandwich makeASandwich(Ingredients... ingredients)e Sub2temboolean contactAliens(Frequency onFrequency) .
Como esses métodos usam parâmetros diferentes e fazem coisas totalmente diferentes, eles são completamente incompatíveis, e não posso simplesmente usar o polimorfismo para resolver esse problema.
Basefornece a maior parte da funcionalidade e tenho uma grande coleção de Baseobjetos. No entanto, todos os Baseobjetos são a Sub1ou a Sub2e, às vezes, preciso saber quais são.
Parece uma má idéia fazer o seguinte:
for (Base base : bases) {
if (base instanceof Sub1) {
((Sub1) base).makeASandwich(getRandomIngredients());
// ... etc.
} else { // must be Sub2
((Sub2) base).contactAliens(getFrequency());
// ... etc.
}
}
Então, criei uma estratégia para evitar isso sem vazamento. Baseagora possui estes métodos:
boolean isSub1();
Sub1 asSub1();
Sub2 asSub2();
E, é claro, Sub1implementa esses métodos como
boolean isSub1() { return true; }
Sub1 asSub1(); { return this; }
Sub2 asSub2(); { throw new IllegalStateException(); }
E Sub2 implementa da maneira oposta.
Infelizmente, agora Sub1e Sub2tenha esses métodos em sua própria API. Então eu posso fazer isso, por exemplo 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(); }
Dessa forma, se o objeto é conhecido por ser apenas um Base , esses métodos não são preteridos e podem ser usados para "converter" a si mesmo para um tipo diferente, para que eu possa invocar os métodos da subclasse. De certa forma, isso me parece elegante, mas, por outro lado, estou abusando das anotações obsoletas como uma maneira de "remover" os métodos de uma classe.
Como uma Sub1instância realmente é uma Base, faz sentido usar herança em vez de encapsulamento. O que estou fazendo bem? Existe uma maneira melhor de resolver este problema?
instanceof, de uma maneira que requer muita digitação, é propenso a erros e dificulta a adição de mais subclasses.
Sub1e Sub2não pode ser usado de forma intercambiável, por que você os trata como tal? Por que não acompanhar seus 'fabricantes de sanduíches' e 'alienígenas' separadamente?