Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java多态函数调用_Java_Polymorphism_Extends - Fatal编程技术网

Java多态函数调用

Java多态函数调用,java,polymorphism,extends,Java,Polymorphism,Extends,无法理解两个函数调用的输出为何为“3”和“4”。因为 g2.foo( t1 ); 在编译时,g2是类型A,它查找在其主类中找不到的foo(类型C),因此它查看其子类B,然后是C。因此foo(…)应该绑定到 public void foo(C p) { System.out.println("5"); } 子类C正确吗 然后在运行时,g2将是类型C并调用foo(cp),这将导致输出为“5”。我不确定我对多态性的逻辑/理解哪里是错误的 class A { public void

无法理解两个函数调用的输出为何为“3”和“4”。因为

g2.foo( t1 );
在编译时,g2是类型A,它查找在其主类中找不到的foo(类型C),因此它查看其子类B,然后是C。因此foo(…)应该绑定到

public void foo(C p) {
    System.out.println("5");
}
子类C正确吗

然后在运行时,g2将是类型C并调用foo(cp),这将导致输出为“5”。我不确定我对多态性的逻辑/理解哪里是错误的

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(ap)
。在运行时
g2
C
的实例中,这意味着调用
C
public void foo(ap)
,并打印3

r2.foo(新的C())

r2
具有编译类型
B
,因此可以在编译时选择
public void foo(ap)
public void foo(bp)
public void foo(bp)
是最好的重载匹配(因为
B
A
更具体)。在运行时,
r2
C
的一个实例,因此调用
C
public void foo(bp)
,并打印4

在编译时,g2是类型A,它查找foo(类型C),在它的主类中找不到foo,因此它查找它的子类B,然后是C。所以foo(…)应该绑定到

你的这种理解是错误的

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
    }
}
在编译期间,由于类型
A
中没有
foo(C)
,它标志着将调用方法
foo(A)
(因为
A
C
的超类型,并且它是最具体的匹配方法)

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

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

 public void foo(A p)

但在运行时,g2是C类的对象,因此每当重写函数时,就会调用public void foo(ap)

,派生类的虚拟表(v-table)将该函数与其实现映射。因此,函数调用将调用该特定类的v表所给出的实现

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

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