はじめに
何番煎じだという話ですが、Goのinterfaceついてどこよりもわかりやすく説明することを目標に記事を書きました。(型としてのinterfaceとは内容が異なります)
要点
1. インターフェースは特定のメソッドを持っている構造体をグループ化する仕組み
2. インターフェース内にメソッドを定義すると、同じインターフェースに属する構造体全てがインターフェース内のメソッドを使用可能
実際にコードを見てみよう
下のコードを見てください。構造体GokuとKrikkinは両方ともメソッドのKamehamehaを使用できます。
package main
import "fmt"
type Goku struct {
Power int
}
func (g Goku) Kamehameha() {
str := fmt.Sprintf("%d Kamehameha", g.Power)
fmt.Println(str)
}
type Krillin struct {
Power int
}
func (k Krillin) Kamehameha() {
str := fmt.Sprintf("%d Kamehameha", k.Power)
fmt.Println(str)
}
例えば、この2つに共通のメソッドであるTaiyokenを追加する場合、また1つ1つ追記しなければなりません。これは面倒ですね。
func (g Goku) Taiyoken() {
fmt.Print("Flash!!\n")
}
func (k Krillin) Taiyoken() {
fmt.Print("Flash!!\n")
}
2つだけなら楽ですが、他にも多くの構造体が同じメソッドを使用するとなると、いちいち書いていられません。そこでインターフェースの出番です。
type Kamesenryu interface {
Kamehameha()
}
Kamesenryuというインターフェースを作成しました。
ここで注目するのは、Kamehameha()の部分です。これはKamehamehaメソッドを持っている構造体は全て、Kamesenryuインターフェースに属するという意味です。インターフェース内に記載されたメソッドはマーキングやラベルのようなものです。
func Taiyoken(k Kamesenryu) {
fmt.Print("Flash!!\n")
}
新たにメソッドであるTaiyokenを定義しました。これでレシーバに指定されたKamesenryuに属する構造体は、全てTaiyokenを使用できるようになりました。
func main() {
g := Goku{Power: 10000}
g.Kamehameha()
Taiyoken(g)
k := Krillin{Power: 1000}
k.Kamehameha()
Taiyoken(k)
}
最後にコードの全てを掲載しておきます。
package main
import "fmt"
type Goku struct {
Power int
}
func (g Goku) Kamehameha() {
str := fmt.Sprintf("%d Kamehameha", g.Power)
fmt.Println(str)
}
type Krillin struct {
Power int
}
func (k Krillin) Kamehameha() {
str := fmt.Sprintf("%d Kamehameha", k.Power)
fmt.Println(str)
}
type Kamesenryu interface {
Kamehameha()
}
func Taiyoken(k Kamesenryu) {
fmt.Print("Flash!!\n")
}
func main() {
g := Goku{Power: 10000}
g.Kamehameha()
Taiyoken(g)
k := Krillin{Power: 1000}
k.Kamehameha()
Taiyoken(k)
}
ご指摘あればワクワクしながら待ってます。