如果我已经完成向上转换,为什么要重写从子类调用的方法?
why overridden method calling from Subclass if i have done up-casting?
我刚刚开始学习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
}
}
谁能解释一下,这是怎么回事??
使用继承时,对调用方法的对象的引用的编译时类型仅用于查看(在编译时)是否可以调用该方法。
但是在调用时,编译时类型是什么并不重要。在这种情况下真正重要的是对象的运行时类型。是Test
,所以先在Test
上搜索方法。
对于 methodOne()
它有点不同:它没有被 Test
覆盖,因此调用其超类 (Example
) 的版本。
Class Test
扩展 Example
并在添加新方法 methodThree
时覆盖 methodTwo
的实现。现在在你的主要
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
中定义的 public 方法的限制 class 因此它是非法调用 exa.methodThree()
(未定义 Example
)。
而对于在 Example
class 处定义的方法,在运行时存在动态绑定,这导致基于 exa
变量指向的引用的具体实现。因此 exa.methodTwo()
调用导致重写函数的执行,因为动态类型是 Test
。由于 Test
不会覆盖 methodOne
调用 exa.methodOne()
将导致 Example
.
定义的实现
如果我们创建 subclass 的对象并使用 supper class 的引用,那么 运行time 时间动态绑定发生意味着在 运行time java决定应该调用哪个东西。
在你的情况下:
1. exa.methodOne();
methodOne 属于 super class 并且它不会在 child class 中被覆盖,所以 parent class 方法将被执行。
在这里,如果你创建像 Test test = new Test();
这样的对象,那么 test.methodOne()
也会给你相同的结果。
exa.methodTwo();
此处 methodTwo 在子 class 中被覆盖,因此在 运行 时间被覆盖的方法将被绑定并执行。
在第三种情况下,它会给出错误,因为您正在使用父 class 引用,但 methodThree() 不是父的一部分,因此会引发编译错误。
如果想调用第三种方法,那么你可以这样调用:Test test = new Test();
test.methodThree()
仅供参考,
为了安全起见,如果我们想要覆盖任何父 class 方法,我们应该始终在子调用方法中使用 @Override 注释。这将有助于避免任何方法覆盖故障。
我刚刚开始学习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
}
}
谁能解释一下,这是怎么回事??
使用继承时,对调用方法的对象的引用的编译时类型仅用于查看(在编译时)是否可以调用该方法。
但是在调用时,编译时类型是什么并不重要。在这种情况下真正重要的是对象的运行时类型。是Test
,所以先在Test
上搜索方法。
对于 methodOne()
它有点不同:它没有被 Test
覆盖,因此调用其超类 (Example
) 的版本。
Class Test
扩展 Example
并在添加新方法 methodThree
时覆盖 methodTwo
的实现。现在在你的主要
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
中定义的 public 方法的限制 class 因此它是非法调用 exa.methodThree()
(未定义 Example
)。
而对于在 Example
class 处定义的方法,在运行时存在动态绑定,这导致基于 exa
变量指向的引用的具体实现。因此 exa.methodTwo()
调用导致重写函数的执行,因为动态类型是 Test
。由于 Test
不会覆盖 methodOne
调用 exa.methodOne()
将导致 Example
.
如果我们创建 subclass 的对象并使用 supper class 的引用,那么 运行time 时间动态绑定发生意味着在 运行time java决定应该调用哪个东西。
在你的情况下:
1. exa.methodOne();
methodOne 属于 super class 并且它不会在 child class 中被覆盖,所以 parent class 方法将被执行。
在这里,如果你创建像 Test test = new Test();
这样的对象,那么 test.methodOne()
也会给你相同的结果。
exa.methodTwo();
此处 methodTwo 在子 class 中被覆盖,因此在 运行 时间被覆盖的方法将被绑定并执行。在第三种情况下,它会给出错误,因为您正在使用父 class 引用,但 methodThree() 不是父的一部分,因此会引发编译错误。 如果想调用第三种方法,那么你可以这样调用:
Test test = new Test();
test.methodThree()
仅供参考,
为了安全起见,如果我们想要覆盖任何父 class 方法,我们应该始终在子调用方法中使用 @Override 注释。这将有助于避免任何方法覆盖故障。