Mam klasy bazowej, Base. Ma dwie podklasy Sub1i Sub2. Każda podklasa ma kilka dodatkowych metod. Na przykład Sub1ma Sandwich makeASandwich(Ingredients... ingredients)i Sub2ma 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.
Basezapewnia większość funkcji, a ja mam dużą kolekcję Baseobiektów. Jednak wszystkie Baseobiekty są albo a Sub1albo 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. Baseteraz ma te metody:
boolean isSub1();
Sub1 asSub1();
Sub2 asSub2();
I oczywiście Sub1implementuje te metody jako
boolean isSub1() { return true; }
Sub1 asSub1(); { return this; }
Sub2 asSub2(); { throw new IllegalStateException(); }
I Sub2wdraża je w odwrotny sposób.
Niestety, teraz Sub1i Sub2mają 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ż Sub1instancja 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.
Sub1i Sub2nie 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”?