我正在学习Java,我得到了以下代码:
public class A {
public void m(A a) { System.out.println("A.m:A"); }
public void m(B b) { System.out.println("A.m:B"); }
}
public class B extends A {
private void m(C c) { System.out.println("B.m:C"); }
public void m(B b) { System.out.println("B.m:B"); }
}
public class C extends A {
public static void main(String args[]) {
A ab = new B();
B bb = new B();
A ac = new C();
ab.m(ac); // My answer: A.m : A || correct
ab.m(ab); // My answer: B.m : B || Correct answer: A.m : A
ab.m(bb); // My answer: B.m : B || correct
bb.m(ac); // My answer: compile error || Correct answer: A.m : A
bb.m(ab); // My answer: B.m : B || Correct answer: A.m : A
bb.m(bb); // My answer: B.m : B || correct
ac.m((A)bb); // My answer: A.m : A || correct
bb.m((B)ac); // My answer: compile error || Correct answer: run-time error [Class cast exception] --> I UNDERSTAND THIS
bb.m((B)ab); // My answer: B.m : B || correct
}
}
我必须写出main函数中调用的结果。 如你所见,我得到了大多数错误的答案。 我想要了解的是,当我有一个用类的超类变量时,我怎样才能确定调用哪个类函数?是使用的子类构造函数
答案 0 :(得分:0)
为了回答这类问题,你需要考虑三件事:
回答(1)查看声明的右侧:ab
和bb
的类型为B
,而ac
的类型为C
}。
要回答(2)请查看声明的左侧:ab
是A
,bb
是B
,ac
是A
。
要回答(3),寻找演员表,并与第(1)部分的类型进行比较。允许将子类转换为基类,如(A)bb
中所示。但是,在(B)ac
中,兄弟之间的转换会导致编译时错误,当编译时类型允许您确定在编译时类型是父级时转换兄弟或运行时错误。 / p>
一旦得到(1)和(2)的答案,并消除了由(3)引起的错误,你需要查看源代码,并从(1)中选择与类型匹配的类的方法重载来自(2)的班级。
答案 1 :(得分:0)
上述答案非常有意义,因此我不打算重复用户已经说过的内容。您的答案不正确的情况(除了您提到的已经理解的情况之外)都与将子类实现创建的超类对象作为参数传递给方法m
。
A ab = new B();
B bb = new B();
A ac = new C();
ab.m(ab); // My answer: B.m : B || Correct answer: A.m : A
bb.m(ac); // My answer: compile error || Correct answer: A.m : A
bb.m(ab); // My answer: B.m : B || Correct answer: A.m : A
在上面的所有这些语句中,您实际上传递的是A
的对象,尽管实现是子类。因此,没有任何进一步的混淆,您可以查找使用对象A
的参数的方法。因为实际的对象实现只能在运行时解决。