超类引用无法在Java中调用子类方法
我对Java中的多态性有一个基本的疑问。我将下面的代码写在一个名为AnimalTestDrive.java的文件中。根据我的说法,下面的代码应该特别使用粗体线,但不幸的是它不是。你能否解释一下原因,我已经给出了以下错误:
I have a basic doubt in polymorphism in Java. I have written the code below in one file named AnimalTestDrive.java. According to me the code below should work specially the line in bold but unfortunately its not. Can you please explain why, I have given the error below:
class Dog extends Animal {
public void dogMethod() {
System.out.println("In Dog method");
}
}
public class AnimalTestDrive {
public static void main(String args[]) {
Dog d = new Dog();
d.dogMethod();
d.animalMethod();
Animal animal = new Animal();
animal.animalMethod();
animal = d;
**animal.dogMethod(); // THIS IS NOT WORKING**
}
}
让我们尝试以与编译器相同的方式查看此行:
Let's try to look at this line the same way that the compiler would:
animal.dogMethod();
首先,它需要找出动物
意思是这很简单 - 它是当前方法中的局部变量,所以它不需要看得太远。
First, it needs to work out what animal
means. That's nice and easy - it's a local variable in the current method, so it doesn't need to look far.
该变量的编译时类型是动物
。编译器不关心变量的值在执行时是什么 - 它只使用有关声明类型的信息。
The compile-time type of that variable is Animal
. The compiler doesn't care what the value of the variable will be at execution time - it only uses the information about the declared type.
那就是它用来试图查找 dogMethod()
在 animal
的上下文中的含义,即键入 Animal
。首先它在 Animal
中查找,然后在 java.lang.Object
中查找(的隐式超类> Animal
) - 但这些类都没有包含 dogMethod
的声明。此时,编译器必须放弃错误 - 它无法找到该方法。该方法在 animal
引用的值的执行时类型上可用并不重要。它必须在编译时使用编译时可用的信息绑定它。
So, that's what it uses to try to look up what dogMethod()
means within the context of animal
, i.e. with type Animal
. First it looks in Animal
, then in java.lang.Object
(the implicit superclass of Animal
) - but neither of those classes contains a declaration of dogMethod
. At that point, the compiler has to give up with an error - it can't find the method. It doesn't matter that the method is available on the execution-time type of the object that the value that animal
refers to. It has to bind it at compile-time, using only the information available at compile time.
在执行时做出的唯一决定是哪一个使用方法的实现 - 例如,如果你调用 animal.toString()
并且 Dog
类有一个覆盖,例如
The only decision made at execution time is which implementation of a method is used - for example, if you called animal.toString()
and the Dog
class had an override, e.g.
@Override public String toString() {
return "I'm a dog";
}
然后编译器会找到 toString()
来自 java.lang.Object
的方法,因此它会知道方法调用是有效的 - 但是实现在 Dog 。
then the compiler would find the toString()
method from java.lang.Object
, so it would know that the method call was valid - but the implementation in Dog
would be used because of the execution-time type of the object.