【问题标题】:What does Base b2 = new Child(); signify?Base b2 = new Child(); 是什么?表示?
【发布时间】:2010-12-15 08:13:34
【问题描述】:
 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();

    }

}

我对上面的代码有些困惑。最让我困惑的一行是

Base b2 = new Child();

 b2.subtract();

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

问题是我们如何或在哪里可以使用这条线,即Base b2 = new Child();

我们应该在什么场景下使用它?请帮忙,会很棒!

【问题讨论】:

  • 基本上你可以在需要 Base 类型的对象时使用它,其行为为 Child

标签: java inheritance


【解决方案1】:

看语句的两部分:

Base b2

声明了一个名为b2 的变量,其类型为Base。如果引用为 null 或引用 Base 的实例或 Base 的子类,您可以分配对该变量的引用。

然后

new Child()

创建Child 的新实例。 ChildBase 的子类,因此可以将构造函数返回的引用赋值给b2 变量。

现在,您只能“看到”Baseb2 的成员,即使实际值在执行时指的是 Child 的实例。但是Base 中的任何方法在Child 中被覆盖 都会在它们被调用时使用被覆盖的版本......所以当你调用时

b2.subtract();

JVM 找出b2 所指对象的实际 类型,并使用该类的subtract 实现——在这种情况下,打印“子减法”的方法。

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

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

List<String> strings = new ArrayList<String>();

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

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

【讨论】:

  • 我认为 OP 的问题是关于在哪里使用 Base b = new Child(); 而不是 Child b = new Child();,不是吗?
  • @khachik:我一直在编辑答案以提供更多细节。目前尚不清楚 OP 在多大程度上理解它的工作原理,并且只是在“最佳实践”建议之后。
  • @on Skeet:我完全同意执行部分。但我想知道这其中的逻辑意义。就像这对逻辑编码有何帮助?
  • b2 类型的变量” - 不是Base 类型和名称b2
  • 您没有提到的一个优点是它不仅允许将来对代码进行更改的灵活性-该变量还允许引用其他实现List&lt;String&gt; 存储在其中。使用一种特定类型的默认值初始化变量的方法并不少见,但有可能将其设置为其他类型的方法。
【解决方案2】:
Base b2 = new Child(); 

您可以将 Super 的引用用于子对象。

对于 b2.method();

在编译时你必须有method();在 BaseClass 中。

在运行时会调用 Object 的方法,所以这里的对象是来自 Base b2 = new Child(); 的 Child

所以孩子的method() 版本将被执行。

用法:

多态性在设计企业级系统时非常有用,因为您可以创建和定义多个接口层,允许外部各方或外部软件以特定方式与您的系统交互。我们都知道发布 API 对系统集成有多大帮助,但如果需要对内部系统进行更改,则可能必须重新发布 API,并且可能必须重新设计集成系统。为避免这种情况,在设计期间应仔细考虑对象 API 以及整个系统 API。确保健壮系统能够处理具有比最初预期更复杂的方法的对象的一种方法是让对象 API 是多态的。这样,系统就知道传递给它的对象的“面孔”,但不必知道临时变化。

另见

【讨论】:

  • life.java 是的,我同意上面的解释。但我想喜欢这条线的用途。在什么场景下可以使用。会有什么帮助?
  • @Sam ,它将为您的 OO 设计制作抽象结构,进一步您将在运行时有机会执行哪个版本的方法
猜你喜欢
  • 2015-09-17
  • 1970-01-01
  • 2012-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-23
  • 1970-01-01
相关资源
最近更新 更多