当定义为BaseClass时,在ExtendedClass对象上调用BaseClass方法

时间:2015-10-29 14:52:54

标签: java

想象一下以下代码:

public class BaseClass {
    private int a;

    public void noReturnNoParam() {
        System.out.println("From Base Class");
    }
}

public class ExtendedClass extends BaseClass {
    private int b;

    @Override
    public void noReturnNoParam() {
        System.out.println("From Extended Class");
    }
}

public class Polymorph {
    public static void main(String... args) {
        BaseClass bc = new BaseClass();
        ExtendedClass ec = new ExtendedClass();
        BaseClass bcec = new ExtendedClass();

        bc.noReturnNoParam();
        ec.noReturnNoParam();
        bcec.noReturnNoParam();
    }
}

输出如下:

From Base Class
From Extended Class
From Extended Class

那么我怎样才能实现这一点,在调用bcec.noReturnNoParam()时调用BaseClass`方法? (并且只有当ExtendedClass对象存储在BaseClass类型中时)?

5 个答案:

答案 0 :(得分:1)

这是OOP基本原则之一的演示。它被称为polymorphism

独立于你的类(你的例子中的BaseClass)看起来它将如何用作初始化的类(ExtendedClass)。

答案 1 :(得分:1)

这称为动态多态性\动态方法绑定,在运行时, 对象类型的JVM调用方法,NOT引用类型。在这种情况下,对象类型是ExtendedClass,因此它是该类的调用方法。 你无法避免它。

答案 2 :(得分:1)

这不是Polymorphism的意图。你可以通过任何方式使你的扩展类在其方法中调用它的超类实现,如

@Override
public void noReturnNoParam() {
    super.noReturnNoParam();    // here base class implementation will be run
    System.out.println("From Extended Class");
}

但是你无法调用基类实现。

  

Java虚拟机(JVM)为其调用适当的方法   每个变量中引用的对象。它没有打电话给   由变量类型定义的方法。这种行为是   称为虚方法调用并演示了一个方面   Java语言中重要的多态性特征。

答案 3 :(得分:1)

您遇到的问题是静态与动态绑定

使用动态绑定,将在运行时动态调用方法。如果您需要澄清,这里有一个很好的小article

据我所知,您将无法像您当前设计的类一样严格调用基本方法。只有派生类'方法才能调用基类',因为你要覆盖它。

因此,即使您将编译器声明为基类,该对象实际上也是派生类的对象,因此,它的方法将在运行时调用。

答案 4 :(得分:1)

这正是多态的概念:

BaseClass bcec = new ExtendedClass();

BaseClass是您为bcec声明的合约。它为您的编译时间提供了有关您可以从bcec获得的信息。它告诉您可以调用noReturnNoParam方法。

ExtendedClass是bcec的实际实现。 JVM在运行时知道bcec.noReturnNoParam()正在调用ExtendedClass中的noReturnNoParam。

以下陈述类似:

ExtendedClass ec = new ExtendedClass();

左边的ExtendedClass是合同,告诉你从ec可以得到什么。右边的ExtendedClass是实际的实现,它在运行时执行。

ExtendedClass扩展了BaseClass,因此ExtendedClass的实例也是BaseClass的一个实例。但是BaseClass的实例可能不是ExtendedClass的实例。这就是下面无法编译的原因:

ExtendedClass abc = new BaseClass();

我给你另一个例子,使这个概念不那么抽象。

class Fruit {
    void taste() {
        System.out.println("delicious!");
    }
}

class Apple extends Fruit{
    void taste() {
        System.out.println("sweet!");
    }
}

class Orange extends Fruit{
    void taste() {
        System.out.println("juicy!");
    }
}

class Polymorph {
    public static void main(String... args) {
        Fruit fruit = new Fruit();
        Apple apple = new Apple();
        Fruit fruit_apple = new Apple();
        Fruit fruit_orange = new Orange();

        fruit.taste(); // prints delicious!
        apple.taste(); // prints sweet!
        fruit_apple.taste(); // prints sweet!
        fruit_orange.taste(); // prints juicy!
    }
}

Orange和Apple都是Fruit。水果/橙子/苹果都有口味,橙子和苹果有自己的口味。你说苹果是一种水果,橙子也是一种水果,但你不能说水果是苹果。