多态性与继承

2022-09-02 03:28:54

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

Animal a = new Dog();

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

但我的问题是:如果我可以通过Dog对象(继承)调用Animal的所有方法,那么我为什么要使用多态性原理呢?我只能声明:

Dog d = new Dog();

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


答案 1

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

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

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

  • 在C++您可以在不产生多态行为的情况下继承类(即不要在基类中标记函数virtual)
  • 在 Objective C 中,您可以在不相关的类上实现一个方法,并从只知道该方法签名的位置调用它。

回到Java,使用多态性的原因是将代码与其反方实现的细节分离:例如,如果您可以编写适用于各种动物的方法,那么当您添加更多子类或实现时,该方法将仍然适用。这与一种与狗紧密耦合的方法形成鲜明对比。Feed(Animal animal)AnimalFeed(Dog dog)

至于

Dog d = new Dog();

声明去,没有一般的理由来避免这一点,如果你知道你的方法的其余部分专门处理狗。但是,在许多情况下,后者并非如此:例如,您的类或方法通常对确切的实现不敏感,例如

List<Integer> numbers = new ArrayList<Integer>();

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

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


答案 2

您可以拥有该类的其他实现,例如 .然后你可以说AnimalCat

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

您可以调用类的方法,而不关心它到底是哪个实现,多态性将调用正确的方法。例如:Animal

a.speak();  // "Woof"

b.speak();  // "Meow"

真的,这不是“多态性与继承”,而是“使用继承的多态性”。


推荐