Java超类调用子类方法

时间:2015-12-09 14:33:19

标签: java class inheritance

我有这些课程:

class A {
  public void f() { System.out.println("f() in A"); }
  public void g() { System.out.println("g() in A"); f(); }
}

class B extends A {
  public void f() { System.out.println("f() in B"); }
}

为什么

B b = new B();
A a = b;
a.g();

打印出来

g() in A
f() in B

而不是

g() in A
f() in A

我有什么遗失的吗?

5 个答案:

答案 0 :(得分:3)

这是因为Java在类的方法上默认使用dynamic dispatch(并强制使用)。

此功能可确保在调用方法时,选择执行该方法的最专业版本。在您的情况下,从B extends A开始,这意味着public void f()的{​​{1}}实施比B的实施更专业。因此,虽然A静态类型为A a,但它是A类型的动态类型,并且选择了该方法。

答案 1 :(得分:2)

是的,即使变量" a"它是A类型,它拥有的对象引用是B类型,所以B中的f()是被调用的。

答案 2 :(得分:1)

https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html

这称为多态性。它允许我们做一些事情,比如拿一个Animal类型的列表,但是当我们把一只猫放进去,然后做animal.performcall()它会打印一个喵喵。这是我老师多年前给我的例子,无论如何:)

答案 3 :(得分:0)

对象的引用变量类型确定可以访问哪些方法。

对象的类确定存在哪些方法。这些存在但无法访问的方法可以通过转换来访问。

即:((B) a).g();允许您访问G的B版本。这仅适用,因为a下面是B

答案 4 :(得分:0)

现在你已经了解了多态性和覆盖。

由于您没有得到预期的输出,我建议通过方法阴影或隐藏来获得预期输出

如果你重新定义基类非静态&派生类中的非私有方法,称为覆盖

在此示例中,A保存B的实例,因此从B而不是A调用f()

如果重新定义基类静态方法/变量是派生类,则称为隐藏阴影

在上面的示例中,只需添加为static方法修改的g(),您将获得所需的输出。现在g()方法

class A {
  public static int i=10;
  public static void f() { 
    System.out.println("f() in A:i="+i); 
  }
  public void g() { System.out.println("g() in A"); f(); }
}

class B extends A {
  public static int i=20;
  public static void f() { 
      System.out.println("f() in B:i"+i); 
  }
}
public class Test2 {
    public static void main(String args[]){
        B b = new B();
        A a = b;
        a.g();
    }
}

输出:

g() in A
f() in A:i=10