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 }
この様な型づけをダックタイピング、と言います。
ダックタイピングは、PythonやRubyなど、動的型付け言語で用いられる、
オブジェクト指向プログラミングの型づけの方法です。
「アヒルの様に歩き、アヒルのように鳴くならば、それをアヒルとみなす」という考え方であり、
「どのようなメソッドを持つか」を、オブジェクトを受付ける基準にするということです。
逆に言えば、あるオブジェクト(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しか受け付けないため、エラーとなる }
参考