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しか受け付けないため、エラーとなる
}
参考