例如:
class RuntimePolymorphismDemo {
public static void main(String[] args) {
Animal ref1 = new Animal();
Animal ref2 = new Dog();
Animal ref3 = new Cow();
Animal ref4 = new Snake();
ref1.whoAmI();
ref2.whoAmI();
ref3.whoAmI();
ref4.whoAmI();
}
}
如果您可以像这样定义它们,那么定义类型为Animal的ref1,ref2,ref3和ref4变量的目的是什么:
Animal ref1 = new Animal();
Dog ref2 = new Dog();
Cow ref3 = new Cow();
Snake ref4 = new Snake();
你可以直接调用whoAmI()方法吗? 你使用父类获得了什么?
感谢。
答案 0 :(得分:1)
在您引用的示例的上下文中看起来是有效且合理的。回到运行时ploymorphism的基本定义是" 相同的界面但不同的实现 "
所以在你的例子中:Animal基本上为你提供了一个界面whoAmI()。但是,您将获得Animal指向的实际类型的行为(这称为运行时调度或动态调度),具体取决于该类型的具体实现:
ref2.whoAmI(); /* will say I am Dog */
ref3.whoAmI(); /* will say I am snake*/
这种行为的重点是什么:这是OOP最重要的概念之一,它可以促进封装。
例如:你可能有一个方法可以做很多事情。它将显示动物名称,动物图片和历史。让我们说该方法看起来像:
public void ShowAnimalInfo(Animal animal)
{
animal.WhoAmI();
var picture = animal.GetImage();
var history = animal.GetHistory();
/* statement and logic to process picture and history on some UI */
}
现在,此方法的使用者可以使用以下方法:
ShowAnimalInfo(new Dog()); /*OR*/
ShowAnimalInfo(new Cow());
如果你注意到,你的方法ShowAnimalInfo()是从实际的动物中抽象出来的,可以通过只使用Animal提供的接口来重新使用,让运行时负责调用实际的实现。
答案 1 :(得分:0)
OOP的全部目的是必须隐藏对象的实现,因此在严格的OOP样式中,当我们使用对象时,我们关心它的协议(接口)以及何时构造我们关心它的实现的对象,赋予它特殊的特性。所以正确的OOP风格是第一个:
Animal ref2 = new Dog();
实例化后,没有'狗'概念,只是一个'动物'。这种误解的产生是因为在大多数现代OOP语言中,Class也可以是Type,但这些实际上是不同的概念。另见这个问题:Object-oriented languages without class concept。