昨天我问了一个类似的问题,但又出现了另一个问题。
class Cat {
public void isClawedBy(Cat c, Kitten k){
System.out.println("Clawed by a cat");
}
}
class Kitten extends Cat{
public void isClawedBy(Kitten k, Cat c){
System.out.println("Clawed by a Kit");
}
}
Cat g = new Cat();
Cat s = new Kitten();
Kitten t = new Kitten();
g.isClawedBy(s,t);
s.isClawedBy(t,s);
t.isClawedBy(t,t);
我感到困惑的问题是t.isClawedBy(t,t);
左右。我理解s.isClawedBy(t,s);
会抛出错误,因为s是静态类型cat。
但是t.isClawedBy(t,t);
正在抛出“方法isClawedBy(Kitten,Cat)对于类型Kitten”的错误是不明确的。如果我将代码更改为t.isClawedBy(s,t);
或t.isClawedBy(t,s);
它可以正常工作,但不确定它为什么不适用于(t,t)。
提前致谢
答案 0 :(得分:1)
这是不明确的,因为Kitten
是Cat
s。
因此,给定:
Cat isClawedBy(Cat c, Kitten k)
Kitten isClawedBy(Kitten k, Cat c)
对于Kitten
,两种方法都可用。 Kitten
是Cat
,因此使用两个Cat.isClawedBy(Cat, Kitten)
参数调用Kitten
符合签名。同样,使用两个Kitten.isClawedBy(Kitten, Cat)
的{{1}}调用也会与签名匹配。
编译器无法确定预期的方法。
答案 1 :(得分:1)
在Java中,方法调用是动态解析的。当您调用方法时,JVM会尝试查找与签名匹配的方法,即方法名称,参数类型和返回类型。它通过查看所用类的方法表来完成此操作,该方法表还将包含超类型的方法签名。
当检查方法表中的签名是否合适时,它将考虑参数(和返回)类型的超类型。在t.isClawedBy(t,t)
的情况下,我们有两个方法可以匹配Kitten
匹配中定义的方法和Cat
匹配中定义的方法 - 请注意这些方法是不同的方法,因为它们具有不同的参数类型
由于两种不同的方法匹配方法,因此调用不明确。
对于isClawed(s,t)
和isClawed(t,s)
,没有歧义,因为s
是小猫,不能是猫。
答案 2 :(得分:0)
这是因为你没有覆盖那个方法。
对于t.isClawedBy(t,t);
,有两种可能的方法可以执行.Cat的isclawed方法和小猫的isclawed方法。
要覆盖方法,参数必须相同。
答案 3 :(得分:0)
小猫延伸猫,所以小猫得到猫的atributs和方法,所以小猫类知道2种方法
但是它知道一个公共的空洞是否被犯罪(小猫k,小猫k)所以当你打电话给isClawedBy(t,t)时它知道该怎么做;