问题
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");
}
}
回答1:
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.
回答2:
There are two important concepts which are competing with each other here.
The first concept is static typing, which means the Java compiler checks the types of your expressions, variables and methods at compile-time, before the code ever gets a chance to run. In this case, the variable myAnimal
is of type Animal
, and the type Animal
does not have a method bark()
, so myAnimal.bark()
is a type error.
The second concept is dynamic binding, which means that the method implementation is selected based on the type of the object at runtime. Since myAnimal
holds a reference to an object of the class Dog
, the call to the move()
method invokes the implementation of that method provided in the Dog
class.
回答3:
Here you declared the myAnimal as Animal and every animal can't bark! i.e myAnimal is referring to Animal here.
Animal myAnimal = myDog;
But for sure Dog is an animal which can bark, hence you need to explicitly cast your myAnimal by letting JVM know its of type Dog and not Just Animal.
So if you change //myAnimal.bark(); to below it will work!
((Dog) myAnimal).bark();
Here we casted myAnimal from Animal to Dog. hence bark() method is allowed and it does not give any compilation issue.
Hope this helps!
来源:https://stackoverflow.com/questions/58721207/upcasting-downcasting-in-java