首页 文章

多态可以做什么继承不能? [重复]

提问于
浏览
1

这个问题在这里已有答案:

想象一下,我们有一个类 Animal ,它扩展到另外三个类: DogCatBird .

该动物类具有 talk()move() 功能 . 通话功能输出"Animal talking",移动功能输出"Animal moving" .

对于狗,这是"Dog moving"和"Dog eating" . 对于 CatBird 类,这种差异与"Cat moving"等并列 .

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

Animal charlietheBird = new Bird()

然后打电话给

charlietheBird.talk()

它会输出

鸟说话

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

HOWEVER!!

我可以干脆做

Bird charlietheBird = new Bird();

然后调用 charlietheBird.poop(); 将提供相同的输出,因为该方法将被覆盖 .

3 回答

  • 2

    多态性可以做什么继承不能?

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

    class Vet {
       private Animal animal; 
       public Vet(Animal animal) {
          this.animal = animal;
       }
    
       public void perfromCheckup() {
          animal.talk();
          animal.poop();
       }
    }
    

    你现在可以说:

    Vet vetWithBird = new Vet(new Bird());
    Vet vetWithDog =  new Vet(new Dog());
    vetWithBird.performCheckup();
    vetWithDog.performCheckup();
    

    请注意如何告诉 VetBirdDog 或任何其他动物进行检查,而无需更改 Vet 类 . 在运行时, Dog 会在进行检查时吠叫,而 Bird 会在进行检查时发出推文 . 想象一下,如果不是 AnimalVet 有一个 Bird 参考:

    class Vet {
       private Bird bird; 
       public Vet(Bird bird) {
          this.bird = bird;
       }
    
       public void perfromCheckup() {
          bird.talk();
          bird.poop();
       }
    }
    

    穷人 Vet 现在只能使用 Bird . 告诉 Vet 使用 Dog ,他会立即拒绝 .

    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.
    

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

  • 2

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

    您举例说明了如何通过继承实现多态性 .

    但你可以用不同的方式看待它:

    移动概念有一个界面:

    interface Movable{
      void move();
    }
    

    动物可以实现这个界面:

    class Dog implements Movable {
      @Override
      public void move(){
        // move the animal
      }
    }
    

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

    class SlimeMold implements Movable {
      @Override
      public void move(){
        // move the animal
      }
    }
    

    很难找到可以用继承表达的那两者之间的“是一种”关系,但是当两者都实现相同的接口时,我们仍然可以对它们应用多态性:

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

    继承是指Java编程的一项功能,它允许您创建从其他类派生的类 . 基于另一个类的类继承另一个类 . 继承的类是父类,基类或超类 .

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

    You can find more information in Objects and Java by Bill Venners Chapter 7: Polymorphism and Interfaces

相关问题