RubyのModuleのように
- インタフェースの実装をStructに埋め込む
i_f.go
package main
import "fmt"
// 料理を作るI/F
type Cooker interface {
Cook() string
}
// 塗るI/F
type Painter interface {
Paint() string
}
// 働くI/F
type Worker interface {
Work() string
}
// 家庭料理を作ることによってCookerI/Fを実装
type HomeCooker struct{}
func (c *HomeCooker) Cook() string {
return "簡単な料理を作ります。"
}
// 日曜大工レベルでPainterI/Fを実装
type SundayPainter struct{}
func (p *SundayPainter) Paint() string {
return "日曜大工レベルでペンキを塗ります。"
}
// 会社で働いてWorkerI/Fを実装
type OfficeWorker struct{}
func (w *OfficeWorker) Work() string {
return "会社で仕事をします。"
}
/*
* お父さんStructは
* CookerI/Fの任意の実装
* PainterI/Fの任意の実装
* WorkerI/Fの任意の実装
* をコンポジションする
*/
type Father struct {
Name string
Cooker
Painter
Worker
}
// ふつうのお父さん
func NewGenericFather() *Father {
return &Father{
"ふつうのお父さん",
// 一般的な実装を持っている
&HomeCooker{},
&SundayPainter{},
&OfficeWorker{},
}
}
// クッキングパパ
type CookingPapa struct {
Name string
Painter
Worker
}
func NewCookingPapa() *CookingPapa {
return &CookingPapa{
"クッキングパパ",
// CookerI/Fは自分自身で実装する
// PainterI/FとWorkerI/Fは一般的な実装を借りる
&SundayPainter{},
&OfficeWorker{},
}
}
func (cp *CookingPapa) Cook() string {
return "なんか工夫したりしてすごい料理を作ります。"
}
/*
* いろんなことをする時に
* Fatherオブジェクトではなく
* 何かしたいことが出来る(責務を持った)
* interfaceを引数に取る
*/
func MakeDinner(c Cooker) string {
return c.Cook()
}
func RepairRoof(p Painter) string {
return p.Paint()
}
func GetMoney(w Worker) string {
return w.Work()
}
func main() {
gf := NewGenericFather()
fmt.Println(gf.Name)
fmt.Println("- ", MakeDinner(gf))
fmt.Println("- ", RepairRoof(gf))
fmt.Println("- ", GetMoney(gf))
cp := NewCookingPapa()
fmt.Println(cp.Name)
fmt.Println("- ", MakeDinner(cp))
fmt.Println("- ", RepairRoof(cp))
fmt.Println("- ", GetMoney(cp))
}