所以我在理解课堂上展示的这个例子时遇到了一些麻烦 - 它应该说明静态和放大之间的微妙之处。 Java中的动态类型。
public class Piece {
public static void main (String[] args) {
Piece p2 = new Knight();
Knight p1 = new Knight();
p1.capture(p2); // call 1; "Knight is bored" is supposed to be printed
p2.capture(p1); // call 2; "knight is bored" is supposed to be printed
}
public void capture () {
System.out.println("Capturing");
}
public void capture (Piece p) {
System.out.println("I'm bored")
}
public class Knight extends Piece {
public void capture (Piece p) {
System.out.println("Knight is bored");
}
public void capture (Knight k) {
System.out.println("TOO SLOW BUDDY");
}
}
这是我对两次调用时会发生什么的理解:
调用1:p1.capture(p2)
从p1调用捕获方法。通过动态类型查找,它看到p1的动态类型是 Knight 。所以它看起来在Knight子类中。 p2作为参数传入。要查看在Knight子类中调用哪个捕获方法,它会检查p2的静态类型,即 piece 。因此,印有“骑士无聊”。这是正确的输出,但我的推理是正确的吗?
致电2:p2.capture(p1)
使用相同的推理,从p2调用捕获方法。通过动态类型查找,它看到p2的动态类型是 Knight 。所以它看起来在Knight子类中。 p1作为参数传入。要查看要调用的捕获方法,它会查看p1的静态类型,即 Knight 。因此,打印出“TOO SLOW BUDDY”。显然,我的推理是错误的,因为那不是真正印刷的。任何方向?
谢谢!
答案 0 :(得分:5)
在第二次调用中,您只能调用Piece类的方法或其子类中的相同方法。这就是为什么它会调用捕获(Piece p)而不是捕获(Knight k)。后者特定于骑士类。
例如,当我们有“List a = new Arraylist();”时,你只能调用在List中声明的方法,而不能在ArrayList中调用类似的方法。
答案 1 :(得分:2)
当您向@Override
方法添加Knight
注释时,它变得清晰。
public void capture (Knight k) {
System.out.println("TOO SLOW BUDDY");
}
此方法未被覆盖 - 它是新的,已在Knight
类中添加。
因此它只能用于Knight
类型的对象 - 例如:Knight k = new Knight();
你没有这样的例子,在Knight
上以Knight
作为参数调用此方法。你在Knight with Piece上调用capture
,在with Piece上调用
p1.capture(p2); // call 1; "Knight is bored" is supposed to be printed
p2.capture(p1); // call 2; "knight is bored" is supposed to be printed
p1.capture(p1); // call 3: TOO SLOW BUDDY <- look here :)
答案 2 :(得分:2)
p2.capture(p1); // call 2; "knight is bored" is supposed to be printed
这里你在Piece类对象上调用capture方法,因为你已经传递了p1(Knight)类引用,它将调用类Knight的重写捕获方法。
public void capture (Piece p) {
System.out.println("Knight is bored");
}
答案 3 :(得分:1)
如果您运行以下代码 -
public class Piece {
public static void main (String[] args) {
Piece p2 = new Knight();
Knight p1 = new Knight();
p1.capture(p2);
p2.capture(p1);
}
public void capture () {
System.out.println("Capturing");
}
public void capture (Piece p) {
System.out.println("I'm bored");
}
}
class Knight extends Piece {
// public void capture (Piece p) {
// System.out.println("Knight is bored");
// }
public void capture (Knight k) {
System.out.println("TOO SLOW BUDDY"+k);
}
}
结果是 -
我很无聊
我很无聊
因此,动态查找检查子类是否已覆盖该函数。
答案 4 :(得分:0)
我记得,我已经学会了“扩展”意味着“将旧版本放在旧版本上但不删除它”,如果你“覆盖”该方法,就会像你描述的那样。 在你的情况下,如果你调用“p1.capture(p1)”,它应该导致“太慢了”(但我没试过)。
答案 5 :(得分:0)
我不认为这个样本告诉你静态和放大之间的差别。动态类型。你甚至不需要考虑超类和子类。它只是告诉你方法定义。 ---&GT;只有当调用者,方法名称,参数名称和参数的类型都相同时,才会调用正确的方法。