Java 多态练习

问题描述 投票:0回答:1

有人可以解释一下编译器/运行时如何运行 示例中的适当方法? 有 6 个类和一个具有不同参数的方法

void m(/* ... */)
。 我知道编译器会分析 声明的类型。 输出始终是来自中产阶级的“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
  }
}
java polymorphism runtime late-binding
1个回答
4
投票

方法重写是在运行时通过查看对象的运行时类型来解决的。编译器也会决定调用哪个方法,但它只能根据表达式的编译时类型来决定。

对于

x
的两次调用,它们都在编译时解析为
Top.m(All)
x
是编译时类型
Top
,因此编译器只能查找
Top
及其超类中声明的方法。编译器发现唯一可用的方法是
m(All)
。在运行时,要调用的方法被解析为
Middle.m(All)
。这是因为
x
的运行时类型实际上是
Middle
,因此运行时会调用
m(All)
中重写的
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)

© www.soinside.com 2019 - 2024. All rights reserved.