使用此代码:
public abstract class A {
private String runNow() {
return "High";
}
public abstract String cos();
static class B extends A {
public String runNow() {
return "Low";
}
public String cos() {
return "cos from B";
}
}
public static void main(String args[]) {
A[] a = new B[] {new B(), new C()};
for (A aa : a) {
System.out.println(aa.runNow() + " " + aa.cos());
}
}
}
class C extends A.B {
public String runNow() {
return "Out";
}
public String cos() {
return "cos from C";
}
}
为什么调用类runNow
的{{1}}方法而不是子类?
答案 0 :(得分:2)
简短回答是"因为runNow()
是private
"。
编译此调用aa.runNow()
时,编译器会看到class A
具有runNow
方法,该方法是私有的,并且您的代码正在调用此私有方法。由于无法覆盖私有方法,因此编译器会将调用路由到A
的{{1}}方法 - 这是唯一知道在此上下文中存在的方法。
runNow()
和B
也以相同名称引入其方法这一事实对编译器无关紧要,因为这些方法在子类中是新的。如果不破坏C
的封装,编译器就无法考虑它们的覆盖,class A
将私有方法指定为runNow
。
答案 1 :(得分:1)
这是因为runNow()是A类中的私有方法。 私有方法不会被继承,因此无法覆盖。
private String runNow(){
return "High";
}
并且您还创建了A类型的引用
A[] a=new B[]{new B(),new C()};
因此,为了完成调用而调用的唯一runNow()是A类,因为编译器不知道B类和C类中的runNow()方法
答案 2 :(得分:1)
因为A类中的方法runNow()
是私有的,所以在B类和C类中你不会覆盖它。当您调用方法aa.runNow()
时,它会直接从A类调用。
尝试做一些实验并将A类中的方法更改为:
private String runNow2() {
return "High";
}
public String runNow() {
return "High";
}
同时将您的System.out
更改为此<:p>
System.out.println(aa.runNow() + " " + aa.cos() + " " + aa.runNow2());
现在结果将符合预期。
希望它有所帮助!
答案 3 :(得分:1)
为什么调用A类的runNow方法而不是从子类
调用
private
方法不会在子类中继承。因此,它们无法被覆盖。由于 runtime-polymorphism 仅适用于重写方法,因此始终会调用runNow
中的A
方法。将runNow
方法中的A
方法更改为public
方法,您将获得所需的输出,因为public
方法是继承的,可以覆盖。
答案 4 :(得分:1)
正如您已经被告知的那样,问题是runNow()
是私有的。因此,它不会被覆盖,通过A
类型的引用访问它会使您进入A
类的定义,而尝试通过B
引用访问它得到子类。
我想指出,这个&#34;奇怪&#34;行为是唯一可行的,因为执行所有这些操作的方法(main
方法)在A
中定义为。如果您的main
方法位于可以访问这些类的另一个类中,那么您将收到一条错误消息,指出该方法根本无法访问。如果您考虑到这一点,可能会更清楚为什么runNow()
和B
中的方法C
不会覆盖A
中的方法。从A之外的任何对象的角度来看,根本没有runNow()
方法 - 它是一个实现细节,而不是A
合同的一部分。因此,它无法被覆盖,runNow()
和B
中的C
只是您在使用B
和{时无法访问的新方法{1}}多态地为C
。