关于java:继承不能做什么多态?

What can polymorphism do that inheritance can't?

本问题已经有最佳答案,请猛点这里访问。

假设我们有一个类Animal,扩展到另外三个类:DogCatBird

这类动物具有talk()move()功能。对话功能输出"动物对话",移动功能输出"动物移动"。

对于一只狗来说,这是"狗动"和"狗吃"。对于CatBird类,这种差异是平行的"猫移动"等。

现在,因为多态性,如果我这样做的话

1
Animal charlietheBird = new Bird()

然后打电话进来

1
charlietheBird.talk()

它将输出

Bird talking

因为输出是在运行时确定的,因为编译器知道charlie是类BirdAnimal类型。

然而!!

我可以简单地做

1
Bird charlietheBird = new Bird();

然后调用charlietheBird.poop();将给出相同的输出,因为方法将被重写。


What can polymorphism do that inheritance can't?

多态性的真正优点可以在运行时看到,而不是在编译时看到。多态性允许您用一个实现替换另一个实现,而不需要更改使用它的代码。让我们以Animal层次结构为例。假设你有一个Vet知道如何对任何动物进行健康检查(是的,他是一个超级兽医)。

1
2
3
4
5
6
7
8
9
10
11
class Vet {
   private Animal animal;
   public Vet(Animal animal) {
      this.animal = animal;
   }

   public void perfromCheckup() {
      animal.talk();
      animal.poop();
   }
}

你现在可以说:

1
2
3
4
Vet vetWithBird = new Vet(new Bird());
Vet vetWithDog =  new Vet(new Dog());
vetWithBird.performCheckup();
vetWithDog.performCheckup();

请注意,您可以告诉Vet在不需要更改Vet类的情况下,对BirdDog或任何其他动物进行检查。在运行时,Dog在进行检查时会发出吠声,而Bird在进行检查时会发出tweet。想象一下,如果Vet不是Animal,而是Vet有一个Bird引用:

1
2
3
4
5
6
7
8
9
10
11
class Vet {
   private Bird bird;
   public Vet(Bird bird) {
      this.bird = bird;
   }

   public void perfromCheckup() {
      bird.talk();
      bird.poop();
   }
}

可怜的Vet现在只能和Bird一起工作了。告诉你的Vet和一个Dog合作,他会立刻拒绝。

1
2
Vet vetWithBird = new Vet(new Bird()); //Works fine. Vet likes birds.
Vet vet = new Vet(new Dog())// compilation error. Sorry I don't like dogs.

总之,多态性允许您替换使用超级类引用的子类实例。继承允许您从父类继承代码,并可能在子类中重新定义该行为,以便您的代码可以在运行时通过多态性利用它。


继承支持多态性,但多态性不依赖于继承。

您给出了一个如何通过继承实现多态性的示例。

但你可以用不同的眼光看待它:

移动概念有一个接口:

1
2
3
interface Movable{
  void move();
}

动物可以实现这个接口:

1
2
3
4
5
6
class Dog implements Movable {
  @Override
  public void move(){
    // move the animal
  }
}

但是一些真菌也可以移动:

1
2
3
4
5
6
class SlimeMold implements Movable {
  @Override
  public void move(){
    // move the animal
  }
}

很难在这两者之间找到可以通过继承来表达的"is a"关系,但是当两者实现相同的接口时,我们仍然可以对它们应用多态性:

1
2
3
4
5
Collection<Movable> movables = new HashSet<>();
movables.add(new Dog());
movables.add(new SlimeMold());
for(Movable movable : movables)
   movable.move();


继承是指Java编程的一个特性,它允许您创建派生自其他类的类。基于另一个类的类继承另一个类。继承的类是父类、基类或超类。

多态性是指编程语言根据对象的数据类型或类不同处理对象的能力。更具体地说,它是为派生类重新定义方法的能力。

您可以在比尔-维纳斯第7章中找到更多关于对象和Java的信息:多态性和接口