假设我有两个类:Animal和Dog。狗是动物的一个子类。我执行以下代码:
Animal a = new Dog();
现在我可以通过一个变量调用Dog类的方法。
但我的问题是:如果我可以通过Dog对象(继承)调用所有Animal的方法而不是为什么我应该使用多态原理?我可以宣布:
Dog d = new Dog();
使用此声明可以使用Animal的所有方法和Dog方法。那么为什么要使用多态?非常感谢你的回答。
答案 0 :(得分:23)
在Java中,多态性和继承的概念是“焊接在一起”;一般来说,它不一定是这样的:
有些语言的继承与多态性脱钩:
virtual
在基类中标记函数)回到Java,使用多态的原因是将代码与其对方的实现细节分离:例如,如果你可以编写一个适用于各种动物的方法Feed(Animal animal)
,当您添加更多子类或Animal
的实现时,该方法将保持适用。这与Feed(Dog dog)
方法形成对比,后者将与狗紧密耦合。
至于
Dog d = new Dog();
声明说,如果你知道你的方法的其余部分特别针对狗,那么没有一般理由可以避免这种情况。但是,在许多情况下,后者并非如此:例如,您的类或您的方法通常对确切的实现不敏感,例如
List<Integer> numbers = new ArrayList<Integer>();
在这种情况下,您可以将new ArrayList<Integer>()
替换为new LinkedList<Integer>()
,知道您的代码将要编译。相反,如果您的numbers
列表被声明为ArrayList<Integer> numbers
,则此类切换可能不太确定。
这称为“编程到接口”。 Stack Overflow上有一个非常好的answer来解释它。
答案 1 :(得分:4)
您可以拥有Animal
类的其他实现,例如Cat
。然后你可以说
Animal a = new Dog();
Animal b = new Cat();
您可以调用Animal
类的方法而不关心它实际上是哪种实现,polymorphism将调用正确的方法。 E.g。
a.speak(); // "Woof"
b.speak(); // "Meow"
实际上,它不是“多态与继承”,而是“使用继承的多态”。
答案 2 :(得分:4)
Polymorphism允许您编写适用于任何Animal
的方法:
public void pet(Animal animal) {
...
}
此方法将接受Dog
,Cat
等,包括尚未编写的Animal
的子类。
如果该方法采用Dog
,则不适用于Cat
等。
答案 3 :(得分:1)
如果你确定它永远是一只狗,那就没有理由。您也可以按照您的描述使用 Dog d = new Dog(); 。但是,假设您使用的是方法而不是构造函数。该方法返回了一只动物,你不知道你会得到哪种动物。你仍然可以在动物身上使用相同的方法(即使它是狗,象猫等)。
为了可扩展性,继承简化了事情。当你想要创造一个也分享一些动物方法的大象或猫时,你可以通过让动物成为超级类来轻松获得它们。
答案 4 :(得分:0)
通常你问的问题更类似于继承与组合:)更多“现实生活”的例子,为什么使用多态性是好的,例如使用策略设计模式。您可以有许多TaxPolicy实现:UsaTaxPolicy,CanadaTaxPolicy,EuTaxPolicy等。如果您有方法calculateFinalPrice,它还必须计算税,那么您注入了正确的实现并执行了良好的计算,无论您是否通过了Usa,Canada或Eu实施。
答案 5 :(得分:0)
继承是动态多态。我的意思是当你删除继承时,你不能再覆盖。