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

ger*_*rky 29 oop polymorphism duck-typing

我对这两个术语感到困惑,这就是我所知道的:

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

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

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

Sim*_*ser 30

多态(在面向对象编程的上下文中)意味着子类可以覆盖基类的方法.这意味着类的方法可以在子类中执行不同的操作.例如:一个类Animal可以有一个方法talk()和子类DogCatAnimal可以让法talk()发出不同的声音.

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

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

  • "多态性意味着子类可以覆盖基类的方法." - 这不仅仅是继承吗? (8认同)
  • @mumble:在面向对象的编程中,它确实是通过继承完成的.但是多态也可以在没有类的情况下完成,例如定义函数`add(int x,int y)`和函数`add(String s,String t)`,它们具有相同的名称,但实际的参数决定了哪个函数是实际上叫. (3认同)
  • 如果您说的是多态性,那么什么是最重要的? (2认同)

And*_*ndy 13

简答:

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

长答案:

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

鸭子打字是打字的一种。并且键入意味着传递的对象不是预期的对象时何时抛出错误。鸭子打字是一种打字,当程序运行并且被调用的方法不可用时,它会抛出错误。静态类型带有编译时检查,因此如果类型信息不匹配,则在编译代码时会抛出错误。这就是打字。

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

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

一方面,如上所述,您不需要继承来拥有多态性。

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


小智 10

这是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()
Run Code Online (Sandbox Code Playgroud)

这是鸭子在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()
Run Code Online (Sandbox Code Playgroud)
  • 在多态性中,我们看到子类(CatDog)从父类(Animal)继承并覆盖方法Talk.
  • 在鸭子类型的情况下,我们不创建子类,而是使用具有相同名称但功能不同的方法创建新类.

  • 在我看来,第一种情况似乎是简单的继承。我真的不认为在像Python这样的动态类型化语言中谈论多态是没有道理的。本质上,这里的第一种情况也是鸭子打字。在Python函数参数中没有类型,因此您可以将任何东西传递给任何函数。那不是多态。这只是动态输入。 (2认同)
  • 在第一个中,它不仅仅是简单的继承,对吧?有一个动物数组,他正在对其元素调用 talk() 。这就是亚型多态性。简单继承的目的基本上只是在类之间共享代码。这显然超出了这一范围。 (2认同)