1

什么是鸭子类型(duck typing)

 2 years ago
source link: https://forrestsu.github.io/posts/go/duck-type/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

什么是鸭子类型(duck typing)

2019年8月10日
| 字数 1499
| Go
| 阅读 813

1 duck type

“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。

比如在 python 中,有很多 file-like 的东西,比如 StringIO, GzipFile, socket; 它们有很多相同的方法,我们把它们当作文件使用。

鸭子类型在动态语言中经常使用,非常灵活,使得 python 不像java那样专门去弄一大堆的设计模式。

下面举例用duck typing来实现多态:

#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输出流:

import sys

sys.stdout = open('stdout.log', 'a') #只要是file-like,不管是什么类型
print 'foo'

sys.stdout = sys.__stdout__ #恢复
print 'bar'

这样就把输出流给写入到文件了。

duck type in Go

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK