前回はインターフェースのメソッドの確約を実装してみました。
Goには構造体を生成しその構造体を返却し、受け取り側はインターフェースで受け取ると言う方法がよく使われるようです。
前回のおさらい
構造体定義
前回のインターフェースの利用では、名前(getName())を実装した構造体であればどんな構造体でも使えるという事が分かりました。それでは実際に使用してみましょう。
今回は例として人構造体(parson)を parson.go へ、猫構造体(cat)を cat.go へ記載します。
package main
// 人の構造体の定義
type parson struct {
name string
age int
}
// 人のメソット定義
func (p parson) getName() string {
return p.name
}
func (p parson) getAge() int {
return p.age
}
package main
// 猫の構造体の定義
type cat struct {
name string
}
// 猫のメソット定義
func (c cat) getName() string {
return c.name
}
使用
インターフェースを定義して、先ほど定義した構造体を使用してみます。
package main
import (
"fmt"
)
// インターフェースの定義
type myInterface interface {
// 必要なメソットを記載する
getName() string
}
func main() {
// 田中さんの名前を表示する
var p parson
p.name = "tanaka"
showName(p) // tanaka が表示される
// 猫の名前を表示する
var c cat
c.name = "cat"
showName(c) // cat が表示される
}
// 名前を表示する関数
func showName(m myInterface) {
fmt.Println(m.getName())
}
具体的なインスタンスの受け取り
ファクトリパターン
それでは、構造体を生成しその構造体を返却し、受け取り側はインターフェースで受け取る と言う事を実践してみましょう。
構造体を受け取るようなファクトリメソットを新たに定義します。
parson.go へ構造体を返却する関数を追加します。
package main
// 人の構造体の定義
type parson struct {
name string
age int
}
// 人のメソット定義
func (p parson) getName() string {
return p.name
}
func (p parson) getAge() int {
return p.age
}
// 構造体を返却する関数
func NewParson(name string, age int) parson {
var p parson
p.name = name
p.age = age
return p
}
cat.goも同様に構造体を返却する関数を追加します。
package main
// 猫の構造体の定義
type cat struct {
name string
}
// 猫のメソット定義
func (c cat) getName() string {
return c.name
}
// 構造体を返却する関数
func NewCat(name string) cat {
var c cat
c.name = name
return c
}
インターフェース定義のメリット
Goでは インターフェースの定義は構造体インスタンスを受け取る側が定義します。これは必要なものだけを使用したいという事が明示的になり、必要のないものは明示されないので何が必要かが明確になります。
package main
import (
"fmt"
)
// インターフェースの定義
type myInterface interface {
// 必要なメソットを記載する
getName() string
}
func main() {
// 鈴木さんの名前を表示する
p := NewParson("suzuki", 20)
showName(p) // suzuki が表示される
// 猫の名前を表示する
c := NewCat("catcat")
showName(c) // catcat が表示される
}
// 名前を表示する関数
func showName(m myInterface) {
fmt.Println(m.getName())
}