本例中多态性背后的逻辑:

时间:2018-01-21 17:20:44

标签: java oop polymorphism

class Base {
    public static void staticMethod(Base bObj) {
        System.out.println("In Base.staticMethod()");
        bObj.instanceMethod();
    }
    public void instanceMethod() {
        System.out.println("In Base.instanceMethod()");
    }
}
class Derived extends Base {
    public static void staticMethod(Base bObj) {
        System.out.println("In Derived.staticMethod()");
        bObj.instanceMethod();
    }
    public void instanceMethod() {
        System.out.println("In Derived.instanceMethod()");
    }
}
public class Main {
    public static void main(String []args) {
        Base bObj = new Derived();
        bObj.staticMethod(bObj);
    }
}

最初,当我看到这个例子时,我确信结果将是:

"In Base.staticMethod()"
"In Base.instanceMethod()".

在第一个Derived对象初始化之后很明显,由于向上转换,它将被解释为Base对象,并且它将调用它所做的基类的静态方法当它调用另一个方法(实例方法)时,它会进入派生函数而不是基类。

为什么,考虑到最初它被认为是Base

3 个答案:

答案 0 :(得分:1)

静态方法没有方法覆盖。因此,bObj.staticMethod()(等同于Base.staticMethod)调用基类的静态方法。

在静态方法中,您正在调用bObj.instanceMethod()。例如,方法覆盖方法,bObj的运行时类型确定执行哪个方法 - 在您的情况下为Derived的实例方法。

答案 1 :(得分:0)

覆盖仅适用于实例方法。对于 sigsuspend() ,该术语称为方法隐藏 See Detail
1.如果使用方法隐藏,则从Subclass隐藏BaseClass的方法。方法选择仅取决于您使用哪个类的引用来调用方法。在您的示例中,因为您正在使用BaseClass(即使您指定Subclass对象,它仍然在类级别它是BaseClass)引用来调用静态方法,它调用BaseClass的方法。如果您将使用如下的SubClass引用,那么它将调用SubClass的静态方法

Static Method
  1. 由于静态方法内部的调用是针对Instance方法的。它在这里使用多态,并调用SubClass的方法。

答案 2 :(得分:0)

<强> TL; DR:

bObj.staticMethod(bObj);仅查看bObj的编译时类型,在您的情况下等同于Base.staticMethod(bObj);。没有压倒一切。

bObj.instanceMethod();仅查看bObj的运行时类,并根据该类选择方法。所以压倒一切在这里工作。

<强>解释

如果你调用静态方法,你应该通过命名类而不是实例来实现。因此bObj.staticMethod(bObj)最好写成Base.staticMethod(bObj)。通常,编译器将为第一个版本发出警告。

那是因为运行时实例对于选择静态方法是无关紧要的。该决定由编译器决定。这就是我们将此方法类型称为“静态”的原因,因为它缺少实例方法的动态方法查找。这意味着没有基于“在点之前”的实例的覆盖。

使用实例表达式误导读者认为实例是相关的,因此不应使用。在静态方法中,没有办法在“点之前”引用实例。静态方法中不存在关键字this。要调用静态方法,您甚至不需要该类的实例(例如,您无法创建Math个实例,但可以毫无问题地调用Math.min()

另一方面,如果调用实例方法,则需要具有该方法的类的实例,并且此实例在方法中获取名称this。无论声明的类型是什么,方法选择都是在运行时根据实例的运行时类完成的。