Base b2 = new Child(); 表示?

Ash*_*wal 4 java inheritance

 class Base {

    public void add() {
        System.out.println("Base ADD");
    }

    void subtract() {
        throw new UnsupportedOperationException("Not yet implemented");
    }

}

class Child extends Base {

    public void add(){
        System.out.println("Child ADD");
    }

    public void subtract() {
        System.out.println("Child Subtract");
    }

}

class MainClass {

    public static void main(String args[]) {

        Base b1 = new Base();
        Base b2 = new Child();

        Child b3 = new Child();

        b1.add();

        b2.subtract();  

        b2.add();
        b3.subtract();

    }

}
Run Code Online (Sandbox Code Playgroud)

我对上面的代码感到有些困惑.让我最困惑的是

Base b2 = new Child();
Run Code Online (Sandbox Code Playgroud)

 b2.subtract();
Run Code Online (Sandbox Code Playgroud)

我所理解的是在编译时编译器检查天气Base类是否有subtract()方法,然后在运行时运行时多态性发生,因为对象是类型Child.

问题是我们如何或在何处使用这条线即 Base b2 = new Child();

在什么情况下我们应该使用它?请帮助,这将是伟大的!

Jon*_*eet 10

看看声明的两个部分:

Base b2
Run Code Online (Sandbox Code Playgroud)

声明一个名为b2type 的变量Base.如果引用为null或引用的实例Base或子类,则可以为该变量分配引用Base.

然后

new Child()
Run Code Online (Sandbox Code Playgroud)

创建一个新的实例Child.Child是的子类Base,因此您可以将构造函数返回的引用分配给b2变量.

现在,您只能"看到" Basethrough的成员b2,即使实际值是指Child执行时的实例.但是任何Base覆盖的方法Child都会在被调用时使用被覆盖的版本......所以当你打电话时

b2.subtract();
Run Code Online (Sandbox Code Playgroud)

JVM找出引用的对象的实际类型b2,并使用该类的实现subtract- 在这种情况下,打印"Child Subtract"的方法.

编辑:你特别问过你可以在哪里使用这种东西,以及它如何帮助......

您可以在任何时候声明更通用类型的变量(超类或接口)时使用它,但是为它分配一个值,该值恰好是接口的子类或实现.另一个例子:

List<String> strings = new ArrayList<String>();
Run Code Online (Sandbox Code Playgroud)

以一般方式声明变量的主要优点是您保持灵活性 - 稍后您可以从使用更改ArrayList<T>为其他实现List<T>,并且代码应该仍然有效.你基本上是在说,"我只需要提供的成员和保证List<T>- 我使用的事实ArrayList<T>是偶然的."

一个类似的例子是决定一个方法应该返回什么类型 - 通常你只想声明你返回一个通用类型(或接口),即使实现知道它返回哪个具体类型.这隐藏了实现细节,允许您稍后更改它们.