鸭子类型在软件开发中意味着什么?


当前回答

在duck类型中,对象的适用性(例如,在函数中使用)取决于是否实现了某些方法和/或属性,而不是基于该对象的类型。

例如,在Python中,len函数可用于任何实现__len__方法的对象。它并不关心该对象是否属于特定类型,例如字符串、列表、字典或MyAwesomeClass,只要这些对象实现了__len__方法,len将与它们一起工作。

class MyAwesomeClass:
    def __init__(self, str):
        self.str = str
    
    def __len__(self):
        return len(self.str)

class MyNotSoAwesomeClass:
    def __init__(self, str):
        self.str = str

a = MyAwesomeClass("hey")
print(len(a))  # Prints 3

b = MyNotSoAwesomeClass("hey")
print(len(b))  # Raises a type error, object of type "MyNotSoAwesomeClass" has no len()

换句话说,MyAwesomeClass看起来像鸭子,也像鸭子一样嘎嘎叫,因此是一只鸭子,而MyNotSoAwesomeClass看起来不像鸭子,也不嘎嘎叫,因此不是一只鸭子!

其他回答

我知道我没有给出一个笼统的答案。在Ruby中,我们不声明变量或方法的类型——所有东西都是某种类型的对象。 规则是"类不是类型"

在Ruby中,类从来都不是(好吧,几乎从来都不是)类型。相反,对象的类型更多地由该对象可以做什么来定义。在Ruby中,我们称之为duck typing。如果一个对象像鸭子一样走路,像鸭子一样说话,那么解释器很乐意把它当作鸭子来对待。

例如,您可能正在编写一个例程,将歌曲信息添加到字符串中。如果你有c#或Java背景,你可能会这样写:

def append_song(result, song)
    # test we're given the right parameters 
    unless result.kind_of?(String)
        fail TypeError.new("String expected") end
    unless song.kind_of?(Song)
        fail TypeError.new("Song expected")
end

result << song.title << " (" << song.artist << ")" end
result = ""

append_song(result, song) # => "I Got Rhythm (Gene Kelly)"

采用Ruby的鸭子输入,您可以编写一些简单得多的东西:

def append_song(result, song)
    result << song.title << " (" << song.artist << ")"
end

result = ""
append_song(result, song) # => "I Got Rhythm (Gene Kelly)"

你不需要检查参数的类型。如果它们支持<<(在结果的情况下)或标题和艺术家(在歌曲的情况下),一切都会正常工作。如果没有,你的方法无论如何都会抛出一个异常(就像你检查了类型一样)。但如果没有检查,你的方法突然变得灵活多了。你可以向它传递一个数组、一个字符串、一个文件或任何其他使用<<追加的对象,它就可以工作了。

在duck类型中,对象的适用性(例如,在函数中使用)取决于是否实现了某些方法和/或属性,而不是基于该对象的类型。

例如,在Python中,len函数可用于任何实现__len__方法的对象。它并不关心该对象是否属于特定类型,例如字符串、列表、字典或MyAwesomeClass,只要这些对象实现了__len__方法,len将与它们一起工作。

class MyAwesomeClass:
    def __init__(self, str):
        self.str = str
    
    def __len__(self):
        return len(self.str)

class MyNotSoAwesomeClass:
    def __init__(self, str):
        self.str = str

a = MyAwesomeClass("hey")
print(len(a))  # Prints 3

b = MyNotSoAwesomeClass("hey")
print(len(b))  # Raises a type error, object of type "MyNotSoAwesomeClass" has no len()

换句话说,MyAwesomeClass看起来像鸭子,也像鸭子一样嘎嘎叫,因此是一只鸭子,而MyNotSoAwesomeClass看起来不像鸭子,也不嘎嘎叫,因此不是一只鸭子!

马特·达蒙解释了《心灵捕手》中的鸭子打字

笔录如下:这里有视频链接。

好吧,我们会有问题吗?

克拉克:没问题。我只是希望你能告诉我鸭子打字到底是什么?我的观点是,鸭系没有很好的定义,也不强

WILL: [interrupting] …and neither is strong typing. Of course that's your contention. You're a first year grad student: you just got finished reading some article on duck typing, probably on StackOverflow, and you’re gonna be convinced of that until next month when you get to the Gang of Four, and then you’re gonna be talking about how Google Go and Ocaml are statistically typed languages with structural sub-tying construction. That's going to last until next year, till you're probably gonna be in here regurgitating Matz, talkin’ about, you know, the Pre-Ruby 3.0 utopia and the memory allocating effects of sub-typing on the GC.

克拉克:(吓了一跳)事实上我不会,因为马茨大大低估了——的影响

WILL:“Matz极大地低估了Ruby 3.0的GC对性能的影响。你是从Donald Knuth的《计算机编程艺术》第98页学到的,对吧?是的,我也读过。你打算为我们剽窃整篇文章吗——你对这件事有什么想法吗?或者,这是你的做法吗,你进入堆栈溢出,你读了r/ruby上一些晦涩的段落,然后你假装,你把它当作你自己的——你自己的想法,只是为了取悦一些女孩,让我的朋友难堪?

[克拉克惊呆了]

威尔:像你这样的人最可悲的是,50年后你会开始自己思考,你会发现生活中有三件事是肯定的。第一,不要那样做。第二,如果它走路像鸭子,那它就是鸭子。第三,你花了十五万美元接受本·科西本可以零美分就能得到的教育。

克拉克:是的,但我会有学位,而你会在我们去滑雪的路上,在汽车餐厅给我的孩子们提供一些廉价的html。

威尔:(微笑)也许吧。但至少我不会没有创意。

(打)

威尔:你遇到了(代码的出现)问题?我想我们可以出去谈谈。

克拉克:没问题

一段时间后:

威尔:你喜欢苹果吗?

克拉克说,嗯?

威尔:你觉得这些苹果怎么样?(砰:威尔把一封信重重地贴在窗户上。)我要谷歌的报价!(出示克拉克的录取通知书,上面有他的面试答案:一张鸭子走路、说话、表现得像一只……鹅)。

不必再说

最后。

(这是对旧答案的一个脚注:)

在编程中,类型可以分为名义类型和结构类型。名义类型考虑类型的整个结构。从谁那里继承的等等。它们显然比结构类型更复杂。例如,在c#和Java中使用名义类型。

结构类型根本不考虑这些问题。对于结构类型,只有单一类型的结构是重要的。这是什么样子。在一个类的例子中。它是否具有相同的参数和预期的类型。这叫做鸭子打字。Duck Typing起源于Duck Test。

Dugtest的意思是:如果某物看起来像鸭子。如果它像鸭子一样游泳。如果它像鸭子一样嘎嘎叫。然后它是一只鸭子。相反地:如果一个测试用例不应用,那么它就不是鸭子。(https://en.wikipedia.org/wiki/Duck_test)

看看语言本身可能会有所帮助;它经常帮助我(我的母语不是英语)。

在鸭子打字中:

1)打字这个词并不是指在键盘上打字(就像我脑海中一直存在的形象那样),而是指确定“那是什么类型的东西?”

2) duck这个词表示决定是如何完成的;这是一种“松散的”定语,比如:“如果它像鸭子一样走路……那它就是一只鸭子。”之所以说“松散”,是因为这个东西可能是一只鸭子,也可能不是,但它是否真的是一只鸭子并不重要;重要的是我能像对待鸭子一样对待它,期待鸭子表现出的行为。我可以喂它面包屑,它可能会向我扑来,向我冲来,或者后退……但它不会像灰熊那样把我吃掉。