読者です 読者をやめる 読者になる 読者になる

DRYな備忘録

Don't Repeat Yourself.

ダックタイピングって一体なんなのよ【golang】

ダックタイピングって

一体何さ。わからないよ

調べた

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型は、DuckDogといった型とは無関係に定義したものだが
  • DuckDogインターフェースの指定するメソッドを全て実装すれば
  • Duck型やDog型として扱うことができる

f:id:otiai10:20140115210138p:plain

画像はここから

そういえば

雑感

  • golangめっちゃ勉強になるっぽい
  • つくりたいものをつくるためにオトナにならないといけない気がする
  • しかし、Now or Never 感もある

DRYな備忘録