【问题标题】:What is the difference between polymorphism and duck typing?多态性和鸭子类型有什么区别?
【发布时间】:2012-07-15 04:33:36
【问题描述】:

我对这两个术语有点困惑,以下是我所知道的:

多态性是指不同类型的对象由一个通用接口处理的能力。而鸭子类型,是一种动态类型,允许不同类型的对象响应相同的方法。

据我了解,多态更多的是创建一个可以在不同类之间共享的接口。鸭子类型是关于松散类型,只要在消息的接收者上找到方法,就可以调用方法。

这是正确的吗?我对这两个很困惑,他们似乎有关系,但我不知道他们的关系是什么。提前非常感谢!

【问题讨论】:

    标签: oop polymorphism duck-typing


    【解决方案1】:

    多态(在面向对象编程的上下文中)意味着子类可以覆盖基类的方法。这意味着一个类的方法可以在子类中做不同的事情。例如:一个类Animal可以有一个方法talk()Animal的子类DogCat可以让方法talk()发出不同的声音。

    Duck typing 意味着代码将简单地接受任何具有特定方法的对象。假设我们有以下代码:animal.quack()。如果给定对象animal 有我们想要调用的方法,那么我们很好(不需要额外的类型要求)。 animal 实际上是 Duck 还是另一种也碰巧嘎嘎的动物都没有关系。这就是为什么它被称为鸭子类型:如果它看起来像一只鸭子(例如,它有一个名为 quack() 的方法,那么我们就可以把这个对象当作一只鸭子)。

    那么这些有关系吗?它们只是编程语言可能具有的单独功能。有些编程语言具有多态性但没有鸭子类型(例如Java)。还有一些语言具有多态性和鸭子类型(例如 Python)。

    【讨论】:

    • 在java中,你可以使用接口来使用某种鸭子类型。
    • 也...通过多态性,您可以改变子类的行为。
    • “多态意味着子类可以覆盖基类的方法。” - 这不只是继承吗?
    • @mumble:在面向对象编程中,它确实是通过继承完成的。但是多态也可以在没有类的情况下完成,例如定义一个函数add(int x, int y)和一个函数add(String s, String t),它们具有相同的名称,但实际参数决定了实际调用的是哪个函数。
    • 如果你说的是多态,那么什么是覆盖?
    【解决方案2】:

    两种类型的多态性

    1. 方法重载(编译时多态)。
    2. 方法覆盖(运行时多态性)。

    方法重载:- 相同的函数名和不同的数据类型称为方法重载

    例子:

      int addTwovalues(int a, int b)
      { return (a+b)}
    
      float addTwovalues(float a, float b)
      { return (a+b)}
    
      Method overriding :- same function name and same data type but different Class
         is known as       Method overriding.
    
    
      class a
     {
      virtual int addtwovalues()
       {  // to do  }
      }
     class b:a
     {
         override int addtwovalues()
       {  // to do  }
    
      }
    
    
    
      a obj=new a();
      obj.addtwovalues();
    
      b objb=new a();
      objb.addtwovalues();  //run time Polymorphism 
    

    【讨论】:

      【解决方案3】:

      这是 Python 中的多态性示例。

      class Animal:
          def __init__(self, name):    # Constructor of the class
              self.name = name
          def talk(self):              # Abstract method, defined by convention only
              raise NotImplementedError("Subclass must implement abstract method")
      
      class Cat(Animal):
          def talk(self):
              return 'Meow!'
      
      class Dog(Animal):
          def talk(self):
              return 'Woof! Woof!'
      
      animals = [Cat('Missy'),
                 Cat('Mr. Mistoffelees'),
                 Dog('Lassie')]
      
      for animal in animals:
          print animal
          print animal.name + ': ' + animal.talk()
      

      这是在 Python 中进行鸭式打字的示例。

      class Duck:
          def quack(self):
              print("Quaaaaaack!")
          def feathers(self):
              print("The duck has white and gray feathers.")
          def name(self):
              print("ITS A DUCK NO NAME")
      
      
      class Person:
          def quack(self):
              print("The person imitates a duck.")
          def feathers(self):
              print("The person takes a feather from the ground and shows it.")
          def name(self):
              print("John Smith")
      
      def in_the_forest(duck):
          duck.quack()
          duck.feathers()
          duck.name()
      
      def game():
          for element in [ Duck() , Person()]:
              in_the_forest(element)
      
      game()
      
      • 在多态性中,我们看到子类(CatDog)从父类 (Animal) 继承并覆盖了 Talk 方法。
      • 在鸭子类型的情况下,我们不创建子类,而是使用具有相同名称但功能不同的方法创建新类。

      【讨论】:

      • 第一个案例对我来说似乎是简单的继承。我真的认为在 Python 这样的动态类型语言中谈论多态性是没有意义的。本质上,这里的第一种情况也是鸭子类型。在 Python 中,函数参数没有类型,因此您可以将任何内容传递给任何函数。那不是多态性。这只是动态类型。
      • 在第一个中,它不仅仅是简单的继承,对吧?有一系列动物,他在其元素上调用talk()。这就是亚型多态性。简单继承的目标基本上只是类之间的代码共享。这显然不止于此。
      • 这是最好的例子
      • 很好的例子,谢谢
      【解决方案4】:

      简答:

      Duck 类型是实现多态性的一种方式。 另一种方法是使用静态类型。

      长答案:

      这里涉及到两个不同的概念,打字和编程技术。

      Duck 打字是打字的一种。并且键入意味着 when 在传递的对象不是预期的情况下抛出错误。 Duck typing 是一种在程序运行时抛出错误并且被调用的方法不可用的类型。静态类型带有编译时检查,所以如果类型信息不匹配,编译代码时会抛出错误。那就是打字。

      多态是一种允许多种类型的对象履行某些职责的编程技术。您可以通过使用基类型来表示所有子类类型来做到这一点。您可以使用鸭子类型来表示具有所需方法的所有不同类型。您可以使用一个接口来表示实现该接口的所有类型。

      有答案说多态是继承,这是不正确的。虽然您可以使用继承来创建多态行为,通常这就是您所做的,但这不是多态的意义所在。

      首先,如上所述,您不需要继承来具有多态性。

      其次,术语“多态性”在依赖于抽象的客户端代码的上下文中更有意义,而不是实现代码。仅仅因为你有一个超类和一些从它继承并覆盖一些方法的其他类并不意味着它是多态的,要创建多态,你必须以多态的方式编写客户端代码来使用这些类。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-25
        • 2021-12-04
        • 1970-01-01
        • 2010-09-12
        • 2016-09-30
        • 2015-01-19
        • 1970-01-01
        相关资源
        最近更新 更多