多态性和鸭子打字有什么区别?

时间:2012-07-16 10:25:02

标签: oop polymorphism duck-typing

我对这两个词有点困惑,这就是我所知道的:

多态性是不同类型的对象由公共接口处理的能力。鸭子打字时,是一种动态类型,允许不同类型的对象响应相同的方法。

据我所知,多态性更多的是创建一个可以跨不同类共享的接口。而鸭子打字是关于松散打字,只要在消息的接收者上找到方法就可以调用方法。

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

4 个答案:

答案 0 :(得分:30)

多态性(在面向对象编程的上下文中)意味着子类可以覆盖基类的方法。这意味着类的方法可以在子类中执行不同的操作。例如:类Animal可以有方法talk()Dog的子类CatAnimal可以让方法talk()变得不同声音。

鸭子打字意味着代码只会接受任何具有特定方法的对象。假设我们有以下代码:animal.quack()。如果给定对象animal具有我们想要调用的方法,那么我们就很好(不需要额外的类型要求)。 animal实际上是Duck还是不同的动物也无关紧要。这就是为什么它被称为鸭子打字:如果它看起来像一只鸭子(例如,它有一个名为quack()的方法,那么我们可以表现得就像那个对象是鸭子一样。)

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

答案 1 :(得分:9)

这是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()
  • 在多态性中,我们看到继承自父类(Cat)并重写方法Talk的子类(DogAnimal)。
  • 如果是鸭子类型,我们不会创建子类,而是使用具有相同名称但功能不同的方法创建新类。

答案 2 :(得分:1)

两种多态性

  1. 方法重载(编译时间多态)。
  2. 方法覆盖(运行时多态性)。
  3. 方法重载: - 相同的函数名称和不同的数据类型称为方法重载

    示例:

      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 :(得分:1)

简短答案:

鸭式打字是实现多态的一种方法。 另一种方法是使用静态类型。

详细答案:

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

鸭子打字是一种打字。而键入意味着何时会在对象传递不正常时引发错误。鸭子类型输入是一种类型的类型,当程序运行且被调用的方法不可用时,它会引发错误。静态类型带有编译时间检查,因此,如果类型信息不匹配,则在编译代码时会引发错误。然后输入。

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

有答案说多态性是继承,这是不正确的。尽管您可以使用继承来创建多态行为,通常这就是您要做的事情,但这并不是多态所要解决的。

对于一个,您不需要继承就可以具有如上所述的多态性。

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