多态性与遗传

假设我有两个类:Animal和Dog。 狗是动物的子类。 我执行以下代码:

Animal a = new Dog(); 

现在我可以通过一个变量调用Dog类的方法。

但我的问题是:如果我可以通过Dog对象(inheritance)调用所有Animal的方法而不是为什么我应该使用多态原理? 我可以声明:

 Dog d = new Dog(); 

有了这个声明,可以使用Animal的所有方法和Dog方法。 那么为什么要使用多态? 非常感谢您的回答。

在Java中,多态性和inheritance的概念是“焊接在一起”; 一般来说,它不一定是这样的:

  • 多态性允许您在不知道类的确切类型的情况下调用类的方法
  • inheritance允许派生类共享其基类的接口和代码

有些语言的inheritance与多态性分离:

  • 在C ++中,您可以inheritance一个类而不会产生多态行为(即不用virtual标记基类中的函数)
  • 在Objective C中,您可以在不相关的类上实现一个方法,并从只知道方法签名的地方调用它。

回到Java,使用多态的原因是将代码与其对立方的实现细节分离:例如,如果你可以编写适用于各种动物的方法Feed(Animal animal) ,方法当您添加更多子类或Animal实现时,它将保持适用。 这与Feed(Dog dog)方法形成对比,后者将与狗紧密耦合。

至于

 Dog d = new Dog(); 

声明说,如果你知道你的方法的其余部分特别针对狗,那么没有一般理由可以避免这种情况。 但是,在许多情况下,后者不是这种情况:例如,您的类或您的方法通常对确切的实现不敏感,例如

 List numbers = new ArrayList(); 

在这种情况下,您可以用new LinkedList()替换new ArrayList() new LinkedList() ,并知道您的代码将要编译。 相反,如果您的numbers列表已声明为ArrayList numbers ,则此类切换可能不是确定的。

这称为“编程到接口”。 Stack Overflow上有一个非常好的答案来解释它。

您可以拥有Animal类的其他实现,例如Cat 。 然后你可以说

 Animal a = new Dog(); Animal b = new Cat(); 

您可以调用Animal类的方法,而无需关心它实际上是哪个实现,并且多态将调用正确的方法。 例如

 a.speak(); // "Woof" b.speak(); // "Meow" 

实际上,它不是“多态与inheritance”,而是“使用inheritance的多态”。

多态性允许您编写适用于任何Animal

 public void pet(Animal animal) { ... } 

此方法将接受DogCat等,包括尚未编写的Animal子类。

如果方法是采取Dog ,它不适用于Cat等。

如果你确定它永远是一只狗就没有理由。 你也可以使用Dog d = new Dog(); 如你所述。 但是,假设您使用的是方法而不是构造函数。 该方法返回了一只动物,你不知道你会得到哪种动物。 你仍然可以在动物身上使用相同的方法(即使它是狗,象猫等)。

出于可扩展性的目的,inheritance简化了事情。 当你想要创造一个也分享一些动物方法的大象或猫时,你可以通过让动物成为超级类来轻松获得它们。

通常你问的问题更类似于inheritance与组合:)更多“现实生活”的例子,为什么使用多态性是好的,例如使用策略设计模式。 您可以有许多TaxPolicy实现:UsaTaxPolicy,CanadaTaxPolicy,EuTaxPolicy等。如果您有方法calculateFinalPrice,它还必须计算税,那么您注入了正确的实现并执行了良好的计算,无论您是否通过了Usa,Canada或Eu实施。

inheritance是动态多态。 我的意思是当你删除inheritance时,你不能再覆盖了。