Java 多态函数调用

Java polymorphism function calls

无法理解为什么两个函数调用的输出是“3”和“4”。对于,

g2.foo( t1 );

在编译时,g2 是类型 A,它寻找 foo(类型 C),它在它的主 class 中找不到,所以它查看它的 children class B,然后是 C。所以 foo(...) 应该绑定到

public void foo(C p) {
    System.out.println("5");
}

subclass C 对吗?

然后在 运行 期间,g2 将输入 C 并调用 foo(C p),这将导致输出“5”。我不确定我的 logic/understanding 多态性哪里错了。

class A {
    public void foo(A p) {
        System.out.println("1");
    }
}

class B extends A {
    public void foo(B p) {
        System.out.println("2");
    }
}

class C extends B {
    public void foo(A p) {
        System.out.println("3");
    }

    public void foo(B p) {
        System.out.println("4");
    }

    public void foo(C p) {
        System.out.println("5");
    }
}

public class HelloWorld {
    public static void main(String[] args) {
        A g2 = new C();
        B r2 = new C();
        C t1 = new C();

        g2.foo(t1); // 3

        r2.foo(new C()); // 4
    }
}

要记住的主要事情是,重载方法是在编译时根据调用该方法的实例的编译时类型选择的。 运行 时间类型仅确定所选方法是否被 运行 时间类型的实现覆盖。

g2.foo( t1 )

g2 有一个编译类型 A,这意味着在编译时只能选择 public void foo(A p)。在 运行 时间 g2C 的实例中,这意味着调用 Cpublic void foo(A p),打印 3.

r2.foo( new C() )

r2 具有编译类型 B,因此可以在编译时选择 public void foo(A p)public void foo(B p)public void foo(B p) 是最好的重载匹配(因为 BA 更具体)。在运行的时候,r2C的一个实例,所以Cpublic void foo(B p)被调用,打印出4.

At compile time, g2 is type A, it looks for foo(type C), which it doesn't find in its main class, so it looks at its children class B, then C. So foo(...) should be bind to ...

你这个理解是错误的

在编译期间,由于类型A中没有foo(C),它标志着方法foo(A)将被调用(因为A是[的超类型=14=] 并且它是匹配的最具体的方法)。

在运行时,C 对特定方法 (foo(A)) 的实现被调用并打印 3。下一次通话也类似。

当你调用 g2.foo(t1) g2 获取 A 的编译类型对象,这意味着 A 的方法即

 public void foo(A p)

但在运行时 g2 是 C Class 的对象,所以 public void foo(A p) 被调用

每当一个函数被覆盖时,派生 class 的虚拟 table (v-table) 就会将该函数映射到其实现。因此函数调用将调用特定 class 的 v-table 给出的实现。

在你的例子中,A g2 = new C();创建 C 的实例,因此 v-table 会将 foo 函数与其(C 的)实现映射。

现在,当函数调用发生时,即在 g2.foo(t1) 上,class C 的实现将被调用,因为它已映射,因此打印 3。