我刚刚开始学习java :: Inheritance并混淆了Up-Casting。
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
}
}
可能有人请解释一下,这里发生了什么?
答案 0 :(得分:9)
使用继承时,对您调用方法的对象的引用的编译时类型仅用于查看(在编译时)是否可以调用该方法。
但是在调用时,编译时类型是什么并不重要。在这种情况下真正重要的是对象的运行时类型。它是Test
,因此首先在methodOne()
上搜索该方法。
对于Test
,它有点不同:它不会被Example
覆盖,因此会调用其超类(model.firstChord.fifth
)中的版本。
答案 1 :(得分:2)
类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
,因此API使用受Example
类中定义的公共方法的限制,因此调用exa.methodThree()
是非法的(不是定义它Example
)。
对于在Example
类定义的方法,在运行时存在动态绑定,这导致基于exa
变量指向的引用的具体实现。因此,exa.methodTwo()
调用会导致执行覆盖函数,因为动态类型为Test
。由于Test
不会覆盖methodOne
,因此调用exa.methodOne()
会导致Example
定义的实施。
答案 2 :(得分:1)
如果我们创建子类的对象并使用supper类的引用,则运行时动态绑定发生意味着在运行时java决定应该调用哪个东西。
在你的情况下:
1. exa.methodOne();
methodOne属于超类,它不会在子类中被重写,因此将执行父类方法。
在这里,如果你创建像Test test = new Test();
这样的对象,那么test.methodOne()
也会给你相同的结果。
exa.methodTwo();
这里的methodTwo在子类中被重写,因此在运行时覆盖的方法将被绑定并且将被执行。
在第三种情况下,它给出错误,因为您正在使用父类引用但methodThree()不是父类的一部分,因此抛出了编译错误。
如果想打电话给第三种方法,那么你可以这样打电话:Test test = new Test();
test.methodThree()
FYI,
为了安全起见,如果我们想覆盖任何父类方法,我们应该总是在子调用方法中使用@Override注释。它将有助于避免任何方法覆盖毛刺。