【问题标题】:Inheritance in Java simple clarificationJava中的继承简单说明
【发布时间】:2012-07-04 10:44:22
【问题描述】:

所以,我有这个:

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。谁可以给我解释一下这个?

【问题讨论】:

    标签: java inheritance


    【解决方案1】:

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

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

    【讨论】:

    • 方法m()class B 中被覆盖。 class Aclass B 对于 m() 具有相同的方法签名。它是被调用的最具体的方法,因为oabclass B 的一个实例,所以被调用的是b.m()。变量oab 只是被引用为A 类型。
    【解决方案2】:
    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 versionm() 被调用的原因。

    【讨论】:

      【解决方案3】:
      A oa = new A();
      B ob = new B();
      A oab = ob;
      

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

      【讨论】:

      • oab 知道有一个函数 void m(),因为类 A 定义了该函数。但是,由于函数的实现在 B 类中被重写,这是对象的真实类型,所以它调用了 B 类中void m() 的实现。
      • 就是这样。最让我感到困惑的是,我将方法 void m() 放在 A 类中作为注释,然后 oab 不再意识到 void m() 。有道理,谢谢
      【解决方案4】:

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

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

      这里oabA 类型的引用变量,但它指向B 类型的对象,即ob,因此在运行时oab.m() 将调用从类m() 覆盖的m() 方法@

      【讨论】:

      • @Faico:很高兴我能帮上忙 :)
      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

        想象一下你有以下情况:

        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()

        【讨论】:

          【解决方案7】:

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

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-12-05
            • 1970-01-01
            • 2019-09-04
            • 2011-12-27
            • 1970-01-01
            • 1970-01-01
            • 2015-03-16
            相关资源
            最近更新 更多