Mam klasy bazowej, Base
. Ma dwie podklasy Sub1
i Sub2
. Każda podklasa ma kilka dodatkowych metod. Na przykład Sub1
ma Sandwich makeASandwich(Ingredients... ingredients)
i Sub2
ma boolean contactAliens(Frequency onFrequency)
.
Ponieważ metody te przyjmują różne parametry i robią zupełnie różne rzeczy, są całkowicie niezgodne i nie mogę po prostu użyć polimorfizmu do rozwiązania tego problemu.
Base
zapewnia większość funkcji, a ja mam dużą kolekcję Base
obiektów. Jednak wszystkie Base
obiekty są albo a Sub1
albo a Sub2
, i czasami muszę wiedzieć, które to są.
Wydaje się, że złym pomysłem jest wykonanie następujących czynności:
for (Base base : bases) {
if (base instanceof Sub1) {
((Sub1) base).makeASandwich(getRandomIngredients());
// ... etc.
} else { // must be Sub2
((Sub2) base).contactAliens(getFrequency());
// ... etc.
}
}
Więc wymyśliłem strategię, aby tego uniknąć bez rzucania. Base
teraz ma te metody:
boolean isSub1();
Sub1 asSub1();
Sub2 asSub2();
I oczywiście Sub1
implementuje te metody jako
boolean isSub1() { return true; }
Sub1 asSub1(); { return this; }
Sub2 asSub2(); { throw new IllegalStateException(); }
I Sub2
wdraża je w odwrotny sposób.
Niestety, teraz Sub1
i Sub2
mają te metody we własnym API. Mogę to zrobić na przykład na 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(); }
W ten sposób, jeśli wiadomo, że obiekt jest tylko a Base
, metody te są nieaktualne i można ich użyć do „rzutowania” na inny typ, aby móc wywołać na nim metody podklasy. W pewnym sensie wydaje mi się to eleganckie, ale z drugiej strony nadużywam przestarzałych adnotacji jako sposobu na „usunięcie” metod z klasy.
Ponieważ Sub1
instancja tak naprawdę jest bazą, sensownym jest użycie dziedziczenia zamiast enkapsulacji. Czy to, co robię dobrze? Czy istnieje lepszy sposób na rozwiązanie tego problemu?
instanceof
, w sposób, który wymaga dużo pisania, jest podatny na błędy i utrudnia dodawanie kolejnych podklas.
Sub1
i Sub2
nie można ich używać zamiennie, to dlaczego traktujesz je jako takie? Dlaczego nie śledzić osobno swoich „producentów kanapek” i „osób kontaktujących się z kosmitami”?