Java 子类化:将被触发的方法是什么?
Java subclassing: what is the method that will get triggered?
我正在学习 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 函数调用的结果。
如您所见,我的大部分答案都是错误的。
我想了解的是,当我有一个创建的 superclass 的 类型的变量时,我如何确定调用什么 class 函数与子class?
的构造函数
为了回答这类问题,您需要考虑三件事:
- 您调用方法的 object 的 run-time 类型是什么?
- 方法参数的compile-time类型是什么?
- 参数转换是否有错误,如果有的话?
回答(1)看右边的声明:ab
和bb
是B
类型,而ac
是C
.
回答(2)看声明的左边:ab
是一个A
,bb
是一个B
,ac
是一个 A
.
要回答 (3),查找强制转换,并与第 (1) 部分中的类型进行比较。允许将 subclass 转换为基数 class,如 (A)bb
。但是,在兄弟姐妹之间转换,如 (B)ac
,当 compile-time 类型让您确定您正在转换兄弟姐妹时会导致 compile-time 错误,或者当 compile-time 时会导致 run-time 错误] 类型是 parent.
一旦你得到了 (1) 和 (2) 的答案,并消除了 (3) 引起的错误,你需要查看源代码,并从 (1) 中选择 class 的方法重载) 与 (2).
中 class 的类型相匹配
上面的回答很有道理,所以我不打算重复那个用户已经说过的话。您的答案不正确的场景(除了您提到的您已经理解的那个)都与将使用子 class 实现创建的超级 class 对象作为参数传递给方法 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
的对象,尽管实现是 class 的子对象。所以没有任何进一步的混淆,你可以寻找正在接受对象 A
参数的方法。因为实际的对象实现只能在 运行 时间解决。
我正在学习 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 函数调用的结果。 如您所见,我的大部分答案都是错误的。 我想了解的是,当我有一个创建的 superclass 的 类型的变量时,我如何确定调用什么 class 函数与子class?
的构造函数为了回答这类问题,您需要考虑三件事:
- 您调用方法的 object 的 run-time 类型是什么?
- 方法参数的compile-time类型是什么?
- 参数转换是否有错误,如果有的话?
回答(1)看右边的声明:ab
和bb
是B
类型,而ac
是C
.
回答(2)看声明的左边:ab
是一个A
,bb
是一个B
,ac
是一个 A
.
要回答 (3),查找强制转换,并与第 (1) 部分中的类型进行比较。允许将 subclass 转换为基数 class,如 (A)bb
。但是,在兄弟姐妹之间转换,如 (B)ac
,当 compile-time 类型让您确定您正在转换兄弟姐妹时会导致 compile-time 错误,或者当 compile-time 时会导致 run-time 错误] 类型是 parent.
一旦你得到了 (1) 和 (2) 的答案,并消除了 (3) 引起的错误,你需要查看源代码,并从 (1) 中选择 class 的方法重载) 与 (2).
中 class 的类型相匹配上面的回答很有道理,所以我不打算重复那个用户已经说过的话。您的答案不正确的场景(除了您提到的您已经理解的那个)都与将使用子 class 实现创建的超级 class 对象作为参数传递给方法 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
的对象,尽管实现是 class 的子对象。所以没有任何进一步的混淆,你可以寻找正在接受对象 A
参数的方法。因为实际的对象实现只能在 运行 时间解决。