技術向上

プログラミングの学び、気になるテクノロジーやビジネストレンドを発信

interface、ダックタイピング【Go】

interfaceを使うと、持つべきメソッドを指定した型(の様なもの)を宣言することができます。

type Human interface {
    Say() string    // Human interfaceは、引数なしで、string型を返すメソッドSay()を持つ必要がある、と指定
}

type Person struct {
    Name string
}

func (p *Person) Say() string {    // 引数を与えたり、返り値の型をstring以外にするとエラーになる。pの中身を変更しない場合、値レシーバーでも可(*を削除)
    return "My name is " + p.Name
}

func main() {
    var mike Human = &Person{"Mike"}    // Human interfaceに紐付けたメソッドが値レシーバーのみの場合、&は不要
    fmt.Println(mike.Say())    // My name is Mike

    var karen Human = &Person{"Karen"}
    fmt.Println(karen.Say())    // My name is Karen
}


この様な型づけをダックタイピング、と言います。
ダックタイピングは、PythonRubyなど、動的型付け言語で用いられる、
オブジェクト指向プログラミングの型づけの方法です。

「アヒルの様に歩き、アヒルのように鳴くならば、それをアヒルとみなす」という考え方であり、
「どのようなメソッドを持つか」を、オブジェクトを受付ける基準にするということです。
逆に言えば、あるオブジェクト(Goはtype)が、異なるメソッドを持っていたり、指定したメソッドを持っていない場合には、
そのオブジェクトをそのinterfaceとしては認めない、ということになります。

ですので、次のような場合はエラーになります。

type Human interface {
    Say() string    // Human interfaceは、引数なしで、string型を返すメソッドSay()を持つ必要がある、と指定
}

type Person struct {
    Name string
}

type Man struct {    // Human interfaceが指定するSay() string メソッドを持っていない
    Name string
}

func (p *Person) Say() string {
    return "My name is " + p.Name
}

func main() {
    var Dan Human = &Man{"Karen"}    // Human interfaceの通り実装しているとは見なすことができないため、エラーとなる
}


interfaceを使用することで、関数が受付ける内容を厳密に指定することができます。

type Human interface {
    Say() string
}

type Animal interface {
        //  メソッドを何も指定しない場合、どんなオブジェクト(type)も受付ける
}

type Person struct {
    Name string
}

type Duck struct {
    Name string
}

func (p *Person) Say() string {
    return p.Name
}

func HiDorrMan(h Human) string {
    if h.Say() == "Mike" {
        return "Come on in"
    } else {
        return "Sorry.."
    }
}

func main() {
    var mike Human = &Person{"Mike"}
    fmt.Println(HiDorrMan(mike))    // Come on in

    var karen Human = &Person{"Karen"}
    fmt.Println(HiDorrMan(karen))    // Sorry..

    var ahiru Animal = &Duck{"Ahiru"}
    fmt.Println(HiDorrMan(ahiru))    // HiDorrMan()は、Humanしか受け付けないため、エラーとなる
}


参考

blog.mmmcorp.co.jp