Java 过载解析 - 为什么 m(cast, cast) 而不是 m(match, cast)
Java Overload resolution - Why m(cast, cast) instead of m(match, cast)
我很确定我不会是第一个遇到这个问题的人,但我找不到答案。这是作业。
class Tier{}
class Fisch extends Tier{}
class Vogel extends Tier{}
class Huhn extends Vogel{}
class Spatz extends Vogel{}
class Karpfen extends Fisch{}
class Super{
public void m(Tier t1, Tier t2){
System.out.println("1");
}
public void m(Tier t, Fisch f){
System.out.println("2");
}
public void m(Fisch f, Tier t){
System.out.println("5");
}
}
class Sub extends Super{
public void m(Tier t1, Fisch t2){
System.out.println("3");
}
public void m(Vogel v, Fisch f){
System.out.println("4");
}
}
public class TierTest{
public static void main(String[] args) {
Tier t1 = new Tier();
Tier t2 = new Vogel();
Fisch f = new Karpfen();
Vogel v1 = new Vogel();
Vogel v2 = new Spatz();
Huhn h = new Huhn();
Karpfen k = new Karpfen();
Super sup1 = new Super();
Super sup2 = new Sub();
sup1.m(h, v2);
sup2.m(v1, k); //4 expected, got 3
sup1.m(t1, t2);
sup1.m(v1, k);
sup1.m(v2, f);
sup2.m(v1, f); //4 expected, got 3
}
}
两次都是 Vogel(bird)(声明和运行时类型)和某种鱼。为什么选择 m(Tier, Fisch) 而不是 m(Vogel, Fisch)?
第一个参数将是一个完美的匹配。剩下的符合我的直觉。
对不起,如果我太麻木了,找不到类似的问题。
周末愉快,
斯蒂芬
这里:
Vogel v1 = new Vogel();
Karpfen k = new Karpfen();
...
Super sup2 = new Sub();
...
sup2.m(v1, k); //4 expected, got 3
sup2
声明为 Super
class 类型。
编译器选择的方法依赖于声明变量的class,而不是运行时实例。
因此,编译器在 Super
class.
中寻找匹配的方法
在 Super
class 中,这些是 m()
潜在的候选方法:
public void m(Tier t1, Tier t2){
System.out.println("1");
}
public void m(Tier t, Fisch f){
System.out.println("2");
}
public void m(Fisch f, Tier t){
System.out.println("5");
}
编译器选择最具体的方法来匹配 v1
和 k
参数声明类型:
已选择此方法:
public void m(Tier t, Fisch f){
System.out.println("2");
}
现在,在运行时,在运行时对象上调用方法(多态性原理)。
由于sup2
变量引用的运行时class是Sub
,所以调用了Sub
的重载方法:
public void m(Tier t1, Fisch t2){
System.out.println("3");
}
第二次调用:
sup2.m(v1, f); //4 expected, got 3
同理
我很确定我不会是第一个遇到这个问题的人,但我找不到答案。这是作业。
class Tier{}
class Fisch extends Tier{}
class Vogel extends Tier{}
class Huhn extends Vogel{}
class Spatz extends Vogel{}
class Karpfen extends Fisch{}
class Super{
public void m(Tier t1, Tier t2){
System.out.println("1");
}
public void m(Tier t, Fisch f){
System.out.println("2");
}
public void m(Fisch f, Tier t){
System.out.println("5");
}
}
class Sub extends Super{
public void m(Tier t1, Fisch t2){
System.out.println("3");
}
public void m(Vogel v, Fisch f){
System.out.println("4");
}
}
public class TierTest{
public static void main(String[] args) {
Tier t1 = new Tier();
Tier t2 = new Vogel();
Fisch f = new Karpfen();
Vogel v1 = new Vogel();
Vogel v2 = new Spatz();
Huhn h = new Huhn();
Karpfen k = new Karpfen();
Super sup1 = new Super();
Super sup2 = new Sub();
sup1.m(h, v2);
sup2.m(v1, k); //4 expected, got 3
sup1.m(t1, t2);
sup1.m(v1, k);
sup1.m(v2, f);
sup2.m(v1, f); //4 expected, got 3
}
}
两次都是 Vogel(bird)(声明和运行时类型)和某种鱼。为什么选择 m(Tier, Fisch) 而不是 m(Vogel, Fisch)?
第一个参数将是一个完美的匹配。剩下的符合我的直觉。
对不起,如果我太麻木了,找不到类似的问题。
周末愉快, 斯蒂芬
这里:
Vogel v1 = new Vogel();
Karpfen k = new Karpfen();
...
Super sup2 = new Sub();
...
sup2.m(v1, k); //4 expected, got 3
sup2
声明为 Super
class 类型。
编译器选择的方法依赖于声明变量的class,而不是运行时实例。
因此,编译器在 Super
class.
在 Super
class 中,这些是 m()
潜在的候选方法:
public void m(Tier t1, Tier t2){
System.out.println("1");
}
public void m(Tier t, Fisch f){
System.out.println("2");
}
public void m(Fisch f, Tier t){
System.out.println("5");
}
编译器选择最具体的方法来匹配 v1
和 k
参数声明类型:
已选择此方法:
public void m(Tier t, Fisch f){
System.out.println("2");
}
现在,在运行时,在运行时对象上调用方法(多态性原理)。
由于sup2
变量引用的运行时class是Sub
,所以调用了Sub
的重载方法:
public void m(Tier t1, Fisch t2){
System.out.println("3");
}
第二次调用:
sup2.m(v1, f); //4 expected, got 3
同理