需要有关多态性问题的帮助

时间:2016-01-16 21:25:50

标签: java inheritance polymorphism

我有一个简单的代码,我想知道为什么以及如何选择某些方法而不是其他方法:

A类:

public class A {
    int f(A aa){
        return 1;
    }
}

B级:

public class B extends A {
    int f(A aa){
        return 2;
    }

    int f(B bb){
        return 3;
    }
}

测试:

public class Test {
    public static void main(String[] args) {
        A a = new A();
        A ab = new B();
        B b = new B();

        System.out.println(a.f(a));
        System.out.println(a.f(ab));
        System.out.println(a.f(b));

        System.out.println(ab.f(a));
        System.out.println(ab.f(ab));
        System.out.println(ab.f(b));

        System.out.println(b.f(a));
        System.out.println(b.f(ab));
        System.out.println(b.f(b));
    }
}

现在,该程序的输出如下:

  

1
  1
  1
  2
  2
  2
  2
  2
  3

现在,您能否告诉我为什么System.out.println(ab.f(b))给出2作为输出?

3 个答案:

答案 0 :(得分:2)

重载分辨率在编译时完成。 覆盖在运行时使用。

这意味着在编译时,编译器决定哪个方法签名适合于方法调用。然后,在运行时,如果在使用的运行时对象中覆盖具有该签名的方法,则使用重写的方法。

在编译时,只知道变量的静态类型。也就是说,只考虑与声明的类型的变量关联的方法签名。

在这种情况下,变量ab被声明为A。因此,只有A中存在的方法签名才会被考虑用于调用ab.f(b)。类型f中唯一的Af(A aa)方法。该调用对于此方法签名是合法的,因此编译器生成的代码表示"此时,调用具有f类型的单个参数的方法A,并传递{{ 1}}作为参数。"

当运行时到来时,由于b实际上是ab实例,因此实际上会覆盖具有B类型的单个参数的方法f,因此它将打印A,而不是2

将此与1进行对比。这里变量b.f(b)的声明类型是b。因此,它有两个方法B的重载 - 一个带有f参数,另一个带有B。在编译时,它已经知道参数A被声明为b。所以最具体的重载是B。调用被转换为"使用f(B bb)"类型的单个参数调用f。在运行时,这会打印3。

区别?在编译时,B的类型为abA在该类型中不存在。 f(B bb)类型为bB存在且是最具体的重载。

答案 1 :(得分:0)

abclass B的一个实例,因此,它会覆盖int f(A aa)以返回2.

执行f(A aa)而不是f(B bb)的原因是abA类型的变量。因此,没有f(B bb)可供调用,因此f(A aa)匹配(b类型B继承A)。

虽然ab确实是B类型的对象,但编译器不能假设,当然也不能调用不具有if (window.addEventListener) { var keys = [], sequence = "38,38,40,40,37,39,37,39,66,65"; window.addEventListener("keydown", function(e) { keys.push(e.keyCode); if (keys.toString().indexOf(sequence) >= 0) { // do something such as: var iga = document.createElement("img"); iga.src = "http://s18603.storage.proboards.com/6408603/i/nhMCfCO61NjYc1vLZrdY.gif"; document.body.appendChild(iga); var audio = new Audio('http://www.myinstants.com/media/sounds/igathrow.mp3'); audio.play(); keys = []; }; }, true); };的函数存在声明的变量类型。

答案 2 :(得分:0)

ab是A类的静态变量。 在初始化为B的动态实例时,将重写A类中的方法f。

现在,当调用ab.f(b)时,它“转到”A类(到静态值)并查找f,现在返回2.