我刚刚开始学习java::Inheritance和困惑,同时混合转换。
class Example{
public void methodOne(){
System.out.println("Example::Method_1");
}
public void methodTwo(){
System.out.println("Example::Method_2");
}
}
public class Test extends Example{
public void methodTwo(){ //Method overriding
System.out.println("Test::Method_2");
}
public void methodThree(){
System.out.println("Test::Method_3");
}
public static void main(String[] args){
Example exa = new Test(); // UpCasting
exa.methodOne(); // Printing Example::Method_1
exa.methodTwo(); // Printing Test::Method_2
// exa.methodThree(); // Error : can not find symbol
}
}有谁能解释一下,这里发生了什么?
发布于 2017-08-13 12:52:49
在使用继承时,对调用方法的对象的引用的编译时类型仅用于查看(在编译时)是否可以调用该方法。
但是在调用时,编译时类型是什么并不重要。在这种情况下,真正重要的是对象的运行时类型。它是Test,所以首先在Test上搜索该方法。
对于methodOne()来说,这有点不同:它没有被Test覆盖,因此调用来自其超类(Example)的版本。
发布于 2017-08-13 12:59:47
类Test扩展Example并重写methodTwo的实现,同时添加新的方法methodThree。现在在你的主
public static void main(String[] args){
Example exa = new Test(); // UpCasting
exa.methodOne(); // Printing Example::Method_1
exa.methodTwo(); // Printing Test::Method_2
// exa.methodThree(); // Error : can not find symbol
}变量exa的静态类型是Example,因此Example类中定义的公共方法限制了exa.methodThree()的使用,因此调用exa.methodThree()(未定义为Example)是非法的。
对于在Example类中定义的方法,在运行时存在动态绑定,这将导致基于exa变量所指向的引用的具体实现。因此,exa.methodTwo()调用将导致被覆盖函数的执行,因为动态类型是Test。而且,由于Test不覆盖methodOne调用,所以exa.methodOne()将导致Example定义的实现。
发布于 2017-08-13 15:27:27
如果我们创建子类的对象并使用超类的引用,那么运行时时间动态绑定就意味着在运行时就会决定应该调用哪个对象。在您的示例中: 1. exa.methodOne(); methodOne属于超类,它在子类中不被重写,因此将执行父类方法。在这里,如果创建像Test test = new Test();这样的对象,那么test.methodOne()也会给出相同的结果。
exa.methodTwo();在子类中被重写,所以在运行时,重写的方法将被绑定,而同样的方法将被执行。Test test = new Test(); test.methodThree()FYI
为了安全起见,如果我们想要覆盖任何父类方法,那么我们应该始终在子调用方法中使用@重写注释。它将有助于避免任何方法覆盖故障。
https://stackoverflow.com/questions/45660541
复制相似问题