Base b2 = new Child(); 表示?

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 b2 

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

然后

 new Child() 

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

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

 b2.subtract(); 

JVM找出b2引用的对象的实际类型,并使用该类的subtract实现 – 在本例中,是打印“Child Subtract”的方法。

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

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

 List strings = new ArrayList(); 

以一般方式声明变量的主要优点是您保持灵活性 – 稍后您可以从使用ArrayList更改为List其他实现,并且代码仍然可以工作。 你基本上是在说,“我只需要List提供的成员和保证 – 我使用ArrayList的事实是偶然的。”

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

 Base b2 = new Child(); 

您可以使用Super的Reference作为孩子的对象。

for b2.method();

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

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

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

用法:

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

另见

  • 关于多态性的标准文件
  • 资源