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();
在什么情况下我们应该使用它?请帮忙,这会很棒!
答案 0 :(得分:10)
请看声明的两个部分:
Base b2
声明一个名为b2
的{{1}}类型的变量。如果引用为null或者引用Base
的实例或Base
的子类,则可以为该变量分配引用。
然后
Base
创建new Child()
的新实例。 Child
是Child
的子类,因此您可以将构造函数返回的引用分配给Base
变量。
现在,您只能“看到”b2
到Base
的成员,即使实际值在执行时指的是b2
的实例。但是Child
中Base
中已被重写的任何方法都会在被调用时使用被覆盖的版本...所以当你打电话时
Child
JVM找出b2.subtract();
引用的对象的实际类型,并使用该类的b2
实现 - 在这种情况下,打印“儿童减去“。
编辑:你明确地问过你可以在哪里使用这种东西,以及它如何帮助...
您可以在想要声明更通用类型的变量(超类或接口)时使用它,但是为它分配一个值,该值恰好是接口的子类或实现。另一个例子:
subtract
以一般方式声明变量的主要优点是您保持灵活性 - 稍后您可以从使用List<String> strings = new ArrayList<String>();
更改为ArrayList<T>
的其他实现,并且代码仍然应该仍然存在工作。你基本上是在说,“我只需要List<T>
提供的成员和保证 - 我使用List<T>
的事实是偶然的。”
一个类似的例子是决定一个方法应该返回什么类型 - 通常你只想声明你返回一个通用类型(或接口),即使实现知道它返回哪个具体类型。这隐藏了实现细节,允许您稍后更改它们。
答案 1 :(得分:1)
Base b2 = new Child();
您可以使用Super的参考作为孩子的对象。
有 b2.method();
在编译时你必须有method();在BaseClass。
在运行时将调用Object的方法,因此这里的对象是来自Base b2 = new Child();
的Child
因此,孩子的method()
版本将被执行。
<强>用法:强>
多态性在设计企业级系统时非常有用,因为您可以创建和定义多个接口层,允许外部方或外部软件以特定方式与您的系统交互。我们都知道在系统集成中使用已发布的API有多大帮助,但如果内部系统更改变得必要,则可能必须重新发布API,并且可能必须重新编写集成系统。为避免这种情况,应仔细考虑对象API以及设计期间的整体系统API。确保健壮的系统可以处理具有比最初预期更复杂的方法的对象的一种方法是使对象API具有多态性。这样,系统知道传递给它的对象的“面”,但不必知道即时更改。
另见