在大学时,我们获得了一个Java程序,并负责了解输出是如何形成的。该计划如下:
interface A {
public void f(A x);
}
interface AA extends A {
public void f(B x);
}
class B implements A {
public void f (A x) {System.out.println("1");}
public void f (B x) {System.out.println("2");}
public void f (C x) {System.out.println("3");}
}
class C implements A,AA {
public void f(A x) {System.out.println("4");}
public void f(B x) {System.out.println("5");}
public void f(C x) {System.out.println("6");}
}
public class Task7 {
public static void main(String[] args) {
B b = new B(); C c = new C();
A ac = c; A ab = b;
AA aac = c;
b.f(b); c.f(c);
ac.f(b); ab.f(b);
aac.f(b); aac.f(c);
}
}
输出为“264154”。我真的不明白最后4个数字是如何解释的。有人可以帮忙吗?
编辑:要进一步解释我的问题: 'b.f(b)'显然会打印出2,因为你给B对象提供B引用,'c.f(c)'将出于同样的原因打印6。
'ab.f(b)'将调用'bf(b)'因为它的动态类型是B.现在,我不明白为什么参数'b',之前已被同一类看到'B',现在被理解为'A',因此“1”被打印而不是“2”。对于其他方法调用也是如此,我只是不明白为什么同一个底层对象的相同参数被不同地解释
答案 0 :(得分:3)
多态性仅应用于.
左侧的对象。无论传递的值如何,编译器都会确定在编译时调用哪个方法签名。
e.g。
B b = new B();
b.f((A) null);
b.f((B) null);
b.f((C) null);
将123
打印为仅在编译时已知的引用类型。
同样,在调用静态方法时,如果使用引用,则只引用类型。
Thread t = null;
t.yield(); // call Thread.yield() so no NullPointerException.
我只是不明白为什么同一个基础对象的相同论点被不同地解释
方法签名是在编译时根据引用类型确定的。
另一种看待它的方法是多态只适用于重写方法,而不是重载方法。
答案 1 :(得分:1)
首先,你必须真正了解多态性。
我不打算解释为什么打印出前两个值,但我觉得有趣的是知道为什么其他值有这些输出。
因此,让我们检查第三个:ac.f(b);
ac是A:A ac = c;
的实例,c是C的实例:C c = new C();
。因此,A ac = new C();
表示ac只能使用C类中的函数,并且在这些函数中它只能调用在A接口中编写的函数:public void f(A x) {System.out.println("4");}
(编译器不关心类型参数部分中的对象)
其他示例:ab.f(b);
这是您在输出中获得的第四个数字。 ab是A的实例:A ab = b
,b是B的实例:B b = new B();
。因此,A ab = new B();
。这意味着ab可以调用A中B 和内声明的所有函数,这就是为什么:public void f (A x) {System.out.println("1");}
。(请记住它们必须在两个部分中声明,而不是仅在一个部分中声明)。