ダックタイピングって
一体何さ。わからないよ
調べた
golangにおけるダックタイピングとは、で一番分かりやすかったのこれ
2014/05/27 追記
つまり、
Go言語ではinterface
を使った型の制限が可能で、逆にinterface
定義において宣言したメソッドをすべて満たすstruct
を作れば、それはそのinterface
を満たす型として扱える。これがダックタイピング。
「ダックタイピング」の名前の由来は「アヒルのように歩き、アヒルのように鳴くものはアヒルに違いない」という言い回しから来ている。
「それ」がアヒルのように歩きアヒルのように鳴きさえするなら、もし「それ」が実は魚のように泳ぐこともできて、蛇のように地を這うことがあったとしても、「それ」はアヒルとして扱って何ら問題なかろう、ということだ。
ポインタ型やメモリ空間を考慮するなら、interface
で制約をかけた場合、呼ばれうるメソッドに対して返り値の大きさを確保するのに、「それ」が魚のように泳ごうとも、蛇のように這おうとも、そこは見てないのだからまあ問題は無い。たしかに。
やってみる
golangのinterfaceを使ったダックタイピング。
今回のお題は
- 「アヒルのように歩き、犬のように吠えるのなら、それはアヒルでありなおかつ犬なのか?」
という問題。
package main import "fmt" // アヒルは、アヒルのように歩く type Duck interface { Duckwalk() string } // 犬は、犬のように吠える type Dog interface { Bark() string } // DuckwalkとBarkというメソッドを持った // ぜんぜん無関係なstructを定義する type Chimera struct { soundOfWalking string soundOfBarking string } func (c Chimera)Duckwalk() string { return c.soundOfWalking } func (c Chimera)Bark() string { return c.soundOfBarking } // 型をチェックするためのメソッド /* * 1) アヒルなら歩かせる * 引数にアヒルしか取らない */ func LetDuckWalk(duck Duck) string { return duck.Duckwalk() } /* * 2) 犬なら吠えさせる * 引数に犬しか取らない */ func LetDogBark(dog Dog) string { return dog.Bark() } // さて、実験 func main() { chimera := &Chimera{ "ぴょこぴょこ", "わんわん", } fmt.Printf("これがキメラだ! => %+v\n", chimera) fmt.Println( "アヒルなら歩いてみせよ!", LetDuckWalk(chimera), "犬なら吠えてみせよ!", LetDogBark(chimera), ) }
その結果
[20:45:47] → go run sample.go これがキメラだ! => &{soundOfWalking:ぴょこぴょこ soundOfBarking:わんわん} アヒルなら歩いてみせよ! ぴょこぴょこ 犬なら吠えてみせよ! わんわん [20:45:51] →
まとめ
Chimera
型は、Duck
やDog
といった型とは無関係に定義したものだがDuck
やDog
インターフェースの指定するメソッドを全て実装すればDuck
型やDog
型として扱うことができる
画像はここから
そういえば
- SlideShareの2013年のPV上位1%スライドになったっぽいです
- Otiai10's year 2013 on SlideShare
- 艦これサマサマです
雑感
- golangめっちゃ勉強になるっぽい
- つくりたいものをつくるためにオトナにならないといけない気がする
- しかし、Now or Never 感もある
DRYな備忘録