鸭子类型在软件开发中意味着什么?
当前回答
在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看起来不像鸭子,也不嘎嘎叫,因此不是一只鸭子!
其他回答
在编程中,类型可以分为名义类型和结构类型。名义类型考虑类型的整个结构。从谁那里继承的等等。它们显然比结构类型更复杂。例如,在c#和Java中使用名义类型。
结构类型根本不考虑这些问题。对于结构类型,只有单一类型的结构是重要的。这是什么样子。在一个类的例子中。它是否具有相同的参数和预期的类型。这叫做鸭子打字。Duck Typing起源于Duck Test。
Dugtest的意思是:如果某物看起来像鸭子。如果它像鸭子一样游泳。如果它像鸭子一样嘎嘎叫。然后它是一只鸭子。相反地:如果一个测试用例不应用,那么它就不是鸭子。(https://en.wikipedia.org/wiki/Duck_test)
简单的解释
鸭子打字是什么?
“如果它走路像鸭子,嘎嘎叫像....等等”——是的,但这是什么意思??!
我们感兴趣的是“对象”能做什么,而不是它们是什么。
让我们用一个例子来分解它:
详情见下文:
Duck Typing功能示例:
想象我有一根魔杖。它有特殊的力量。如果我挥舞魔杖,对一辆车说“开车!”,那么,它就会开车!
它对其他东西有用吗?不确定,所以我在卡车上试了试。哇,它也能开车!然后我在飞机上、火车上和1 Woods(这是一种人们用来“驾驶”高尔夫球的高尔夫球杆)上尝试了一下。他们都开车!
但它能用在茶杯上吗?错误:KAAAA-BOOOOOOM !结果不太好。====>茶杯不能开车!!咄! ?
这就是duck typing的基本概念。这是一个先试后买的系统。如果有效,一切都好。但如果失败了,就像手榴弹还在你手上一样,它会在你脸上爆炸。
换句话说,我们感兴趣的是对象能做什么,而不是对象是什么。
那么像c#或Java等语言呢?
如果我们关心的对象实际上是什么,那么我们的魔术只会对预先设置的,授权的类型起作用——在这种情况下是汽车,但对其他可以驾驶的对象无效:卡车,轻便摩托车,突突车等。它不能在卡车上工作,因为我们的魔杖期望它只能在汽车上工作。
换句话说,在这种情况下,魔杖非常仔细地观察物体是什么(它是一辆汽车吗?),而不是物体能做什么(例如汽车、卡车等能不能开车)。
让卡车驾驶的唯一方法是,如果您能够以某种方式让魔杖同时期待卡车和汽车(也许通过“实现一个公共接口”)。这可以通过一种叫做“多态”的技术来实现,也可以通过使用“接口”来实现——它们是一样的东西。如果你喜欢漫画,想要一个解释,看看我关于界面的漫画。
总结:关键外卖
在duck类型中,重要的是对象实际上可以做什么,而不是对象是什么。
序言
我试图通过去除迂腐的细微差别和学术语言来保持它的简单/有趣。这种方法并不适合所有人——如果你更喜欢学术定义,可以看看维基百科上关于“回避输入”的文章,或者《心灵捕手》中马特·达蒙对“回避输入”的解释;)
代码示例
但是高尔夫球杆怎么能像汽车一样“驾驶”呢?他们不一样吗?但如果你使用的是Ruby这样的语言:
class Car
def drive
"I"m driving a Car!"
end
end
class GolfClub
def drive
"I"m driving a golf club!"
end
end
def test_drive(item)
item.drive # don't care what it is, all i care is that it can "drive"
end
car = Car.new
test_drive(car) #=> "I'm driving a Car"
club = GolfClub.new
test_drive(club) #=> "I"m driving a GolfClub"
看看语言本身可能会有所帮助;它经常帮助我(我的母语不是英语)。
在鸭子打字中:
1)打字这个词并不是指在键盘上打字(就像我脑海中一直存在的形象那样),而是指确定“那是什么类型的东西?”
2) duck这个词表示决定是如何完成的;这是一种“松散的”定语,比如:“如果它像鸭子一样走路……那它就是一只鸭子。”之所以说“松散”,是因为这个东西可能是一只鸭子,也可能不是,但它是否真的是一只鸭子并不重要;重要的是我能像对待鸭子一样对待它,期待鸭子表现出的行为。我可以喂它面包屑,它可能会向我扑来,向我冲来,或者后退……但它不会像灰熊那样把我吃掉。
我看到很多答案都在重复这句老话:
如果它长得像鸭子,叫声也像鸭子,那它就是鸭子
然后深入解释可以使用duck typing做什么,或者一个似乎进一步混淆了概念的示例。
我觉得没什么用。
这是我发现的关于鸭子打字的最好的简单英语回答:
Duck Typing意味着对象是根据它能做什么来定义的,而不是根据它能做什么来定义的 它是什么。
这意味着我们不太关心对象的类/类型,而更关心可以对其调用哪些方法以及可以对其执行哪些操作。我们不关心它的类型,我们只关心它能做什么。
它是一个用于没有强类型的动态语言中的术语。
其思想是,为了调用对象上的现有方法,您不需要指定类型——如果在对象上定义了方法,则可以调用它。
这个名字来源于一句话“如果它看起来像鸭子,叫起来像鸭子,那它就是鸭子”。
维基百科有更多的信息。