0

所以,我有这个:

public class A {

    public int a = 0;
    public void m(){
        System.out.println("A"+a);
    }
}

和这个:

public class B extends A {

    public int a = 5 ;
    public void m (){
        System.out.println("B"+a);
    }
    public static void main(String[] args) {
        A oa = new A();
        B ob = new B();
        A oab = ob;
        oa.m();
        ob.m();
        oab.m();

        System.out.println("AA"+oa.a);
        System.out.println("BB"+ob.a);
        System.out.println("AB"+oab.a);
    }
}

输出:

A0
B5
B5
AA0
BB5
AB0

我不明白为什么oab.m(); 输出是B5而不是A0。谁可以给我解释一下这个?

4

7 回答 7

9

这就是多态性的全部意义所在。的具体类型oabB(因为对象是用 创建的new B())。所以方法B.m()被调用。

查看http://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29中的 Animal 示例,了解它为何有用。当你有一只动物,而这只动物是猫时,你希望它会说“喵!” 当你让它说话时。

于 2012-07-04T10:46:34.743 回答
1
B ob = new B();
A oab = ob;

类似于

A oab=new B();

I don't understand why oab.m(); output is B5 instead of A0

因为您创建对象B并将其引用到 A 所以m()被继承,这就是为什么被调用B's version的原因。m()

于 2012-07-04T10:59:55.247 回答
0

想象一下,您有以下内容:

public class C extends A {

public int a = 7 ;
public void m (){
    System.out.println("C"+a);
}

现在,如果你的 Main 方法中有这个......

C oc = new C();
A oac = oc;
oac.m();

...您希望最后一次调用输出特定于 C 类的内容。

关键是B 是 AC 是 A,但它们每个都有 A 包含的值的更具体版本,当您请求这些数据时,应该返回它们的具体版本。

现在你可以这样做:

// Get an instance of B or C, but you don't
// care which - could be either:
A someVersionOfA = getAnInstanceOfA(); 

// This works no matter if you've got an instance
// of B or C, but the result should vary accordingly:
someVersionOfA.m();

正如其他人提到的,将A视为“动物”,将B视为“猫”,将C视为“狗”。如果m()的意思是“发出一些声音”,那么调用 m() 应该会导致“喵”或“汪!” 取决于返回的实例getAnInstanceOfA()

于 2012-07-04T11:15:17.817 回答
0

在 Java 中有类似后期绑定(多态性)的东西。这意味着方法的代码不是在编译时(早期绑定)而是在运行时链接的。在调用JVM 时,正在从引用(在您的情况下)oab.m();检查对象的实际类型(类),并基于该信息调用该类的方法代码。这就是为什么返回。aobBoab.m();B5

您还需要知道后期绑定仅适用于方法,而不适用于字段。对于字段值将由引用类型确定,因此oab.a将返回0not 5

于 2012-07-04T11:04:58.803 回答
0
A oa = new A();
B ob = new B();
A oab = ob;

从上面的代码中,ob 是 B 类的一个实例。它可以存储在 A 类的变量中,因为 A 扩展了 B。但是由于存储的 Object 实例是 B 的,因此它不知道 A 的 m() 函数。因此输出是 B5

于 2012-07-04T10:46:45.760 回答
0

在继承中,实际的方法调用取决于实际对象的类型,而不是引用的类型。

 B ob = new B();
 A oab = ob;

oab是一个类型的引用变量,A但它指向类型的对象,Bob在运行时将从类oab.m()调用重写m()的方法B

于 2012-07-04T10:47:28.370 回答
0

您刚刚将 B 的内部地址复制到 A 一个,并替换它。

B继承自A,所以没有编译问题。

最后,对 A 的引用被销毁,它现在是对 B 的引用的副本

于 2012-07-04T13:54:47.297 回答