class A {}
class B extends A {
void xx(){};
}
Do jakiego rzutowania dochodzi tutaj ?
A a = new B();
To nie jest rzutowanie. Wiemy że B
dziedziczy z A
. Przez to wiemy że B
JEST A
. Podobnie jak, skoro Dog
dziedziczy z Animal
to wiemy że Dog
JEST Animal
. Wszędzie tam gdzie możemy użyć zwierzęcia, możemy użyć psa.
Wiem że skoro B
jest A
, to wszędzie tam gdzie możemy użyć A, możemy użyć też B. Nie potrzeba rzutowania.
PS: Powiem Ci inaczej. Rozważmy taką sytuację:
class A {
void methodA() {}
}
class B extends A {
void methdoB(){};
}
A a = new A();
a.methodA(); // ok
a.methodB(); // nie da się, klasa A nie ma metody B
A a = new B();
a.methodA(); // ok
a.methodB(); // nie da się, mimo że to na prawdę klasa B, to jest zadeklarowana jako A i nie ma pewności że jest
metoda methodA
B b = new A(); // błąd, to że B jest A, nie znaczy że A jest B. Nie każde zwierzę jest psem
B b = new B(); // ok
A a = new B();
B b = a; // nie da się, mimo że wiemy że w zmiennej a tak na prawdę jest B, to jest zadeklarowana jako A, i nie ma pewności że to obiekt tej klasy
A a = new B();
B b = (B)a; // nie ma pewności że w zmiennej a jest obiekt klasy B, ale ponieważ rzutujemy to zmuszamy język żeby zaufał że w zmiennej a jest obiekt klasy B, mimo że jest zadeklarowany jako A
Podsumowując, "rzutować w dół" nie musisz dlatego że przez sam fakt że B dziedziczy z A, i można używać B wszędzie tam gdzie B. Rzutowanie "w górę" jest wtedy kiedy coś jest zadeklarowane jako A, wiesz na pewno że to jest B, i chcesz skorzystać z jakiejś metody B.