Duck typing
本文为译文,点击 此处查看原文。
在计算机程序设计中,Duck typing
是Duck test
的一个应用程序 —— “如果它像鸭子一样走路,像鸭子一样嘎嘎叫,那么它一定是鸭子” —— 用于确定一个对象是否可以用于特定目的。对于普通
类型,适用性由对象的类型决定。在duck
类型中,对象的适用性是由某些方法和属性的存在而决定的,而不是对象本身的类型。[1]
1. 示例
这是Python 3中的一个简单示例,演示了如何在任何上下文中使用任何对象,直到以不支持的方式使用为止。
class Duck:
def fly(self):
print("Duck flying")
class Airplane:
def fly(self):
print("Airplane flying")
class Whale:
def swim(self):
print("Whale swimming")
for animal in Duck(), Airplane(), Whale():
animal.fly()
输出:
Duck flying
Airplane flying
AttributeError: 'Whale' object has no attribute 'fly'
2. 在静态类型语言中
某些通常是静态类型的语言,如Boo
和c#
的版本4,有额外的类型注释[2][3],指示编译器安排类的类型检查在运行时而不是编译时进行,并在编译后的输出中包含运行时类型检查代码。
3. 与其他类型系统的比较
3.1 结构化类型体系
Duck类型
与结构化类型
(Structural type)相似,但不同于结构化类型。结构化类型是一个静态类型系统,它通过类型的结构来确定类型兼容性和等价性,而duck类型是动态的,仅通过在运行时访问的类型结构的一部分来确定类型兼容性。
OCaml、Scala、Go、Elm[4]、Gosu 和 PureScript 语言在不同程度上支持结构类型。
3.2 协议与接口
协议和接口可以提供duck类型
的一些好处,但是duck类型的不同之处在于没有定义显式接口。例如,如果第三方库实现了一个不能修改的类,客户端就不能使用该类的实例,即使该类实际上满足接口需求,但该实例的接口对该库来说是未知的。(这个问题的一个常见解决方案是适配器模式。) Duck类型可以做到这一点。同样,为了兼容性,必须满足所有接口。
3.3 模板或泛型类型
模板、泛型函数或方法在一个静态类型上下文中应用duck test
;这通常带来了静态和动态类型检查
的所有优点和缺点。Duck类型还可以更加灵活,因为只需要实现在运行时实际调用的方法,而模板需要实现所有在编译时无法证明不可用的方法。
示例包括使用模板的C++和D语言,它们是由Ada泛型开发的。
4. 批评
4.1 对术语本身的批评
术语“duck typing
”的使用被认为是多余的,因为动态绑定
等其他术语更清楚地表达了这个概念[5]。静态类型检查的支持者, duck typing
暗示typing
的缺失,使其与术语typing
的结合显得不连贯。
5. 其他资料
6. 参考文献
- “Glossary — Python 3.7.1 documentation”. docs.python.org. Retrieved 2018-11-08.
- Boo: Duck Typing Archived October 6, 2008, at the Wayback Machine
- “Anders Hejlsberg Introduces C# 4.0 at PDC 2008”. Retrieved 30 January 2017.
- Czaplicki, Evan. “Core Language · An Introduction to Elm”. Retrieved 30 January 2017.
- Lippert, Eric (2 Jan 2014). “What is “duck typing”?”. Fabulous adventures in coding. Retrieved 25 May 2016.