1 duck type
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。
比如在 python 中,有很多 file-like
的东西,比如 StringIO, GzipFile, socket;
它们有很多相同的方法,我们把它们当作文件使用。
鸭子类型在动态语言中经常使用,非常灵活,使得 python 不像java那样专门去弄一大堆的设计模式。
2 例子
下面举例用duck typing来实现多态:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#coding=utf-8
class Duck:
def quack(self):
print "Quaaaaaack!"
class Bird:
def quack(self):
print "bird imitate duck."
class Doge:
def quack(self):
print "doge imitate duck."
def in_the_forest(duck):
duck.quack()
duck = Duck()
bird = Bird()
doge = Doge()
for x in [duck, bird, doge]:
in_the_forest(x)
|
再举个例子,我们来hack输出流:
1
2
3
4
5
6
7
|
import sys
sys.stdout = open('stdout.log', 'a') #只要是file-like,不管是什么类型
print 'foo'
sys.stdout = sys.__stdout__ #恢复
print 'bar'
|
这样就把输出流给写入到文件了。
duck type in Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
package duck_type
import (
"fmt"
"testing"
)
type Programmer interface {
WriteHelloWorld() string
}
type GoProgrammer struct {
}
func (g *GoProgrammer) WriteHelloWorld() string {
return "fmt.Println(\"Hello World\")"
}
type JavaProgrammer struct {
}
func (j *JavaProgrammer) WriteHelloWorld() string {
return "System.out.Println(\"Hello World\")"
}
//Duck type entry
func PrintHelloWorld(p Programmer) {
fmt.Printf("%T, %s\n", p, p.WriteHelloWorld())
}
func TestDuckType(t *testing.T) {
g := new(GoProgrammer)
t.Log(g.WriteHelloWorld())
j := new(JavaProgrammer)
t.Log(j.WriteHelloWorld())
//duck type, 入参数只能为Pointer
PrintHelloWorld(g)
PrintHelloWorld(j)
}
|
参考
题图:hongkong-victoria-harbor-duck