我有一些像这样的代码:
abstract class ExampleOne {
int dataOne = 1000;
abstract void display();
}
class ExampleTwo extends ExampleOne {
int dataTwo;
ExampleTwo(int varOne) {
dataTwo = varOne;
}
public void disp() {
System.out.println("Testing");
}
public void display() {
System.out.println(dataOne);
}
}
class Example {
public static void main(String args[]) {
ExampleOne obj = new ExampleTwo(20);
obj.disp();
obj.display();
}
}
当我编译它时,我收到一个错误:
obj.disp();
^
symbol: method disp()
location: variable obj of type ExampleOne
为什么会这样?
我正在将ExampleTwo
的实例分配给ExampleOne
,为什么Java不选择ExampleOne
实例而不是ExampleTwo
?
同样的概念适用于dynamic polymorphism
!
为什么会这样?
答案 0 :(得分:9)
由于obj
的类型为ExampleOne
,编译器将在obj
类中的ExampleOne
上搜索您调用的方法,如果找不到,则会抛出错误。
为什么Java不选择ExampleOne实例而不是ExampleTwo?
这是因为编译时检查是基于引用类型而不是实际对象类型完成的。然后,在运行时调用的实际方法是根据被引用的实际对象决定的。这就是我们所说的方法调用的 动态调度 。
您可以向disp()
类添加一个抽象的ExampleOne
方法,只是为了确保编译器对调用感到满意。
abstract class ExampleOne{
int dataOne=1000;
abstract void display();
abstract void disp();
}
答案 1 :(得分:4)
您的方法仅在ExampleTwo
中定义,但不在ExampleOne
中定义。这会导致编译错误。
答案 2 :(得分:1)
您的对象类型为ExampleOne
。即使您创建了ExampleTwo
的实例,编译器已知的对象类型(即方法和成员)也是ExampleOne
,但没有声明disp()。
如果您希望以多态方式使用它,则应在disp()
中声明一个抽象方法ExampleOne
答案 3 :(得分:1)
基类对象只能访问自己的类Methods
。但disp()
不是它的方法。这就是你得到错误的原因。
为了避免错误,你可以这样做:
ExampleTwo obj=new ExampleTwo(20);
obj.disp();
obj.display();
答案 4 :(得分:1)
那么,
背后的概念是,通过这个java contruct,您将使用ExampleTwo的版本调用ExampleOne的方法。
意味着,您只能调用引用变量类型的方法(在您的情况下,它是ExampleOne)。但是调用的方法版本将是底层对象类型(即ExampleTwo)。并且它由多态性促进。
值得一提的是,您可以将对象分配给其类型的任何引用变量或其任何超类,在层次结构中。