Używaj ogólnych zamiast downcastingu. „Downcasting” jest zły, przechodząc z bardziej ogólnego typu na bardziej szczegółowy:
Animal a = hunter.captureOne();
Cat c = (Cat)a; // ACK!!!!!! What if it's a Dog? ClassCastException!
... ufasz, że a
to kot, ale kompilator nie może tego zagwarantować. Może się okazać, że jest to pies w czasie wykonywania.
Oto, gdzie możesz użyć ogólnych:
public class <A> Hunter() {
public A captureOne() { ... }
}
Teraz możesz określić, że chcesz łowcę kotów:
Hunter<Cat> hunterC = new Hunter<Cat>();
Cat c = hunterC.captureOne();
Hunter<Dog> hunterD = new Hunter<Dog>();
Dog d = hunterD.captureOne();
Teraz kompilator może Gwarantujemy że hunterC przechwyci tylko koty i psy hunterD tylko przechwytywania.
Używaj więc zwykłego polimorfizmu, jeśli chcesz obsługiwać określone klasy jako ich podstawowy typ. Upcasting to dobra rzecz. Ale jeśli znajdziesz się w sytuacji, w której musisz obsługiwać określone klasy jako ich własne typy, na ogół używaj rodzajów ogólnych.
Lub, naprawdę, jeśli okaże się, że musisz spuszczać, skorzystaj z generycznych.
EDYCJA: bardziej ogólny przypadek ma miejsce, gdy chcesz odłożyć decyzję, jakie rodzaje typów obsługiwać. Zatem typy stają się parametrem, a także wartościami.
Powiedz, że chcę, aby moja klasa Zoo zajmowała się Kotami lub Gąbkami. Nie mam wspólnej super klasy. Ale nadal mogę używać:
public class <T> Zoo() { ... }
Zoo<Sponge> spongeZoo = ...
Zoo<Cat> catZoo = ...
stopień, w jakim to zablokujesz, zależy od tego, co próbujesz zrobić;)
addAnimals(List<Animal>)
i dodać Listę kotów!