Java 多态练习
Java Polymorphism Exercise
谁能解释一下 compiler/runtime 如何运行
示例中的适当方法?
有 6 个 classes 和一个具有不同参数的方法 void m(/* ... */)
。
我知道编译器会分析
声明的类型。
中间的 class.
的输出总是 "M"
public class All {}
public class Most extends All {}
public class Special extends Most {}
public class Top {
public void m( All p ) { System.out.println("A"); }
}
public class Middle extends Top {
public void m( All p ) { System.out.println("M"); }
public void m( Special p ) { System.out.println("L"); }
}
public class Bottom extends Middle {
public void m( Most p ) { System.out.println("V"); }
public void m( Special p ) { System.out.println("X"); }
}
public class Main {
public static void main(String[] args) {
All all = new All();
Most most = new Most();
Special special = new Special();
Top x = new Middle();
Top y = new Bottom();
Middle z = new Bottom();
x.m( most ); // Output is M
x.m( special ); // Output is M
y.m( all ); // Output is M
y.m( special ); // Output is M
z.m( all ); // Output is M
z.m( most ); // Output is M
}
}
方法覆盖在运行时通过查看对象的运行时类型来解决。编译器也会决定调用哪个方法,但它只能根据表达式的编译时类型来决定。
对于 x
的两次调用,它们都在编译时解析为 Top.m(All)
。 x
是编译时类型 Top
,因此编译器只能查找在 Top
及其超类中声明的方法。编译器发现唯一可用的方法是 m(All)
。在运行时,要调用的方法解析为 Middle.m(All)
。这是因为 x
的运行时类型实际上是 Middle
,所以运行时会调用重写的 m(All)
in Middle
。为什么它不调用 Middle.m(Special)
?编译器已经决定 Top.m(All)
应该被调用。运行时将仅检查运行时类型是否已覆盖它。编译器不知道有 Middle.m(Special)
因为 x
是编译时类型 Top
.
y
上的两个调用是相似的。 y
的编译时类型仍然是Top
,所以编译器将方法解析为Top.m(All)
。 y
是运行时类型 Bottom
。由于 Bottom
继承自 Middle
,它也覆盖了 Top.m(All)
。实现与 Middle
中的相同。因此在运行时调用覆盖的方法。
对z
的两次调用有点不同,但最终还是解析为Middle.m(All)
。 z
的编译时类型是 Middle
,因此两个调用都解析为 Middle.m(All)
。请注意,没有 Middle.m(Most)
,因此调用 z.m(most)
仍将解析为 Middle.m(All)
。在运行时,该方法仍然解析为 Middle.m(All)
,因为运行时类型 Bottom
不会覆盖 Middle.m(All)
.
谁能解释一下 compiler/runtime 如何运行
示例中的适当方法?
有 6 个 classes 和一个具有不同参数的方法 void m(/* ... */)
。
我知道编译器会分析
声明的类型。
中间的 class.
public class All {}
public class Most extends All {}
public class Special extends Most {}
public class Top {
public void m( All p ) { System.out.println("A"); }
}
public class Middle extends Top {
public void m( All p ) { System.out.println("M"); }
public void m( Special p ) { System.out.println("L"); }
}
public class Bottom extends Middle {
public void m( Most p ) { System.out.println("V"); }
public void m( Special p ) { System.out.println("X"); }
}
public class Main {
public static void main(String[] args) {
All all = new All();
Most most = new Most();
Special special = new Special();
Top x = new Middle();
Top y = new Bottom();
Middle z = new Bottom();
x.m( most ); // Output is M
x.m( special ); // Output is M
y.m( all ); // Output is M
y.m( special ); // Output is M
z.m( all ); // Output is M
z.m( most ); // Output is M
}
}
方法覆盖在运行时通过查看对象的运行时类型来解决。编译器也会决定调用哪个方法,但它只能根据表达式的编译时类型来决定。
对于 x
的两次调用,它们都在编译时解析为 Top.m(All)
。 x
是编译时类型 Top
,因此编译器只能查找在 Top
及其超类中声明的方法。编译器发现唯一可用的方法是 m(All)
。在运行时,要调用的方法解析为 Middle.m(All)
。这是因为 x
的运行时类型实际上是 Middle
,所以运行时会调用重写的 m(All)
in Middle
。为什么它不调用 Middle.m(Special)
?编译器已经决定 Top.m(All)
应该被调用。运行时将仅检查运行时类型是否已覆盖它。编译器不知道有 Middle.m(Special)
因为 x
是编译时类型 Top
.
y
上的两个调用是相似的。 y
的编译时类型仍然是Top
,所以编译器将方法解析为Top.m(All)
。 y
是运行时类型 Bottom
。由于 Bottom
继承自 Middle
,它也覆盖了 Top.m(All)
。实现与 Middle
中的相同。因此在运行时调用覆盖的方法。
对z
的两次调用有点不同,但最终还是解析为Middle.m(All)
。 z
的编译时类型是 Middle
,因此两个调用都解析为 Middle.m(All)
。请注意,没有 Middle.m(Most)
,因此调用 z.m(most)
仍将解析为 Middle.m(All)
。在运行时,该方法仍然解析为 Middle.m(All)
,因为运行时类型 Bottom
不会覆盖 Middle.m(All)
.