只是对如何回答答案是错误的。
class Cat {
public void isClawedBy(Cat c){
System.out.println("Clawed by a cat");
}
}
class Kitten extends Cat{
public void isClawedBy(Kitten c){
System.out.println("Clawed by a Kit");
}
}
如果调用以下内容
Cat g = new Cat();
Cat s = new Kitten();
Kitten t = new Kitten();
g.isClawedBy(t);
s.isClawedBy(t);
t.isClawedBy(t);
答案如何: 猫抓了 猫抓了 由小猫抓住
我很困惑为什么s.isClawedBy(t)= Cat Clawed。 由于动态类型的s是小猫,而t是小猫。 是因为参数不同,所以它不会覆盖它吗?
另一部分我很困惑。 //注意参数已被交换。
class Cat {
public void isClawedBy(Kitten c){
System.out.println("Clawed by a cat");
}
}
class Kitten extends Cat{
public void isClawedBy(Cat c){
System.out.println("Clawed by a Kit");
}
}
如果调用以下内容
Cat g = new Cat();
Cat s = new Kitten();
Kitten t = new Kitten();
g.isClawedBy(t);
s.isClawedBy(t);
t.isClawedBy(t);
输出是: 猫抓了 猫抓了 被猫抓住
调用t时它是如何工作的?
答案 0 :(得分:3)
关于第二个查询:t.isClawedBy(t)
提供Clawed by Cat
的输出。
由于t
是Kitten
且方法t.isClawedBy(t)
中传递的参数也是Kitten
,因此将调用超类Cat
中的方法,因为它完全符合论据。
答案 1 :(得分:0)
Class Kitten不会覆盖isClawedBy(Cat c)
。它添加了一种新方法isClawedBy(Kitten c)
。在调用s
时,运行时会将Cat
视为s.isClawedBy(t)
,并最终调用Cat方法。
如果您将Kitten改为:
class Kitten extends Cat{
@Override
public void isClawedBy(Cat c){
System.out.println("Clawed by a Kit");
}
}
然后你会看到你想要的输出。更有趣的是,你可以这样做:
((Kitten) s).isClawedBy(t);
您将看到正确的方法。
答案 2 :(得分:0)
我很困惑为什么s.isClawedBy(t)= Cat Clawed。由于动态类型的s是小猫,而t是小猫。
的引用类型为Cat
,但包含Kitten
个对象。 t具有引用类型Kitten
并保存对象Kitten
。当在运行时运行该方法时,首先检查引用类型是否具有这样的方法,然后调用该方法的最具体版本。由于子类不重写方法(参数中的不同类型),因此调用引用类型中的方法。
对于你的第二部分,它发生了完全相同的事情,没有重载,并且小猫确实可以作为Cat传递给引用类型中的方法所以再次这个方法是层次结构中最具体的一个,它叫做。
答案 3 :(得分:0)
至于第一个问题;
覆盖分辨率在运行时完成,但重载分辨率在编译时完成。
由于你的方法的签名不相同(不同的参数类型。一个是另一个的子类并不重要),它们正在超载。
由于在编译时解析,编译器不知道实例类型是什么;只有声明的类型。
对于编译器,s.isClawedBy(t)
是声明类型 isClawedBy(Kitten)
的方法Cat
。
编译器说:“是的,猫可以用它的方法接受小猫,这就是这种方法的用法”
因此,在运行时,编译器选择了哪个将调用ALREADY的方法。查找不是在运行时执行的。
因此,在运行时,尽管s
实际上是一个Kitten对象,但仍会调用Cat方法。