WIKI讲鸭子类型 已经很清晰了,我接触这个概念是在看雨痕大神的 《Go语言学习笔记》 一书得来的,作者再讲 Golang的接口类型 说就是Duck type。

图片来源: 嘎嘎叫的小狗――快乐的鸭子类型
如下代码实现go的接口
package main import ( "fmt" ) type User struct { name string age byte } type Manager struct { User title string } func (u User) ToString() string { return fmt.Sprintf("%+v", u) } func (m Manager) PrintIt() string { return "good" } // 接口类型 type Print interface { PrintIt() string ToString() string } func main() { var admin Manager admin.name = "方朋" admin.age = 26 admin.title = "厂长" fmt.Println(admin.ToString()) // 只要包含接口所需的全部方法,即实现了该接口 var p Print = admin fmt.Println(p.PrintIt()) fmt.Println(p.ToString()) }鸭子类型本质体现的是面向接口的编程,对于Go来说,接口是一种契约,是多个方法的集合。就像鸭子一样,有叫、跑、游泳的方法我们说这是鸭子, 对于Go,接口实现比较简洁,只要目标类型方法集内包含接口声明的全部方法,就称实现了该接口,不用做显示声明。
对于OOP来说, 体现的是面向继承的编程,但”鸭子类型”像多态一样工作,只是没有继承。
“鸭子类型”的语言是这么推断的:走起来像鸭子、游起泳来像鸭子、叫起来也像鸭子,那它就可以被当做鸭子。 也就是说,它不关注对象的类型,而是关注对象具有的行为(方法)。
上述就是鸭子类型的表现,也就是 任何拥有这样的正确的”走”和”叫”方法的对象都可被函数接受的这种行为。
如下python代码演示:
class Duck(object): def quack(self): print("鸭子呱呱叫") def swim(self): print("鸭子游泳") class Person(object): def quack(self): print("这人模仿鸭子呱呱叫") def swim(self): print("这人模仿鸭子游泳") def interfaces(duck): """ 定义一个接口, 约定呱呱叫和游泳的契约 接收一个对象, 看这个对象所拥有的方法存不存在,不存在触发异常 如果都存在, 不管是人还是真鸭子, 都被认为是鸭子 :param duck: :return: """ duck.quack() # 呱呱叫 duck.swim() # 游泳 def game(): donald = Duck() # 唐老鸭 jack = Person() # Jack interfaces(donald) interfaces(jack) game() # out print: # 鸭子呱呱叫 # 鸭子游泳 # 这人模仿鸭子呱呱叫 # 这人模仿鸭子游泳在Python中, 鸭子类型的最典型例子就是类似 file (file-like)的类 。这些类可以实现file的一些或全部方法,并可以用于file通常使用的地方。例如, GzipFile , cStringIO ,套接字( socket )也和文件共同拥有许多相同的方法。然而套接字缺少 tell() 方法,不能用于 GzipFile 可以使用的所有地方。这体现了鸭子类型的可伸缩性:一个类似file的对象可以实现它有能力实现的方法,且只能被用于它有意义的情形下。
“鸭子类型”没有任何静态检查,如类型检查、属性检查、方法签名检查等。,一切都靠契约和自觉性,所以在可能会在运行时因为不具备某种特定的方法而抛出异常。
Duck-typing avoids tests using type() or isinstance() . Instead, it typically employs the EAFP (Easier to Ask Forgiveness than Permission) style of programming.
在Python里EAFP原则描述了异常处理的使用。例如相对于检查一个自称为类似Duck的对象是否拥有一个 quack() 方法(使用 if hasattr(mallard, "quack"): ... ),人们通常更倾向于用异常处理把对quack的调用尝试包裹起来:
try: mallard.quack() except (AttributeError, TypeError): print "mallard并l