I am trying to understand upcasting and downcasting in Java and I am confused by the following scenario (about my code, which is below):
First - why is it that the code does not compile when I include the line myAnimal.bark();
,
and Second - (assuming I comment out myAnimal.bark();
) why does calling myAnimal.move()
print "moveDog"
instead of "moveAnimal"
? Isn't myAnimal
restricted to methods from the Animal
class because we have declared its type to be Animal
, even though we are setting it to a type of Dog
?
Any help is greatly appreciated! Here is the code:
public class Animal {
public void move() {
System.out.println("moveAnimal");
}
public static void main(String[] args) {
Dog myDog = new Dog();
Animal myAnimal = myDog;
myAnimal.move();
//myAnimal.bark();
}
}
class Dog extends Animal {
@Override
public void move() {
System.out.println("moveDog");
}
public void bark() {
System.out.println("bark");
}
}
With the implicit upcast at this line:
Animal myAnimal = myDog;
You are not doing anything to change the underlying instance myDog
. What you are doing is assigning it to a variable of a type one level higher in the inheritance tree. Effectively, this restricts which methods can be called to only those defined in Animal
, but does not change how those methods resolve.
Because you have restricted the methods available to only those defined on the parent class Animal
, the compiler cannot resolve Dog#bark()
, since it is a method of Dog
, and the variable myAnimal
is defined to be of type Animal
which has no #bark
method.
#move()
is a method of both Animal
and Dog
, so it resolves, but it resolves to the method defined on Dog
, since myAnimal
still refers to an instance of Dog
, despite being upcast.