機能を拡張する(go)

```
embedの練習
```

# goで機能を引き継いだ感じで実装

```go:実装
type Animal struct {
	Name string
}

func (a *Animal) Eat(something string) {
	fmt.Print(a.Name, "は", something, "を食べた")
}

type Cat struct {
	Animal
}
```

CatはAnimalを実装した。
継承では無いので複数実装できて便利。

```go:実装例
type Animal struct {
	Name string
}
type Enjoy struct {
	Playing bool
}
type Cat struct {
	Animal
	Enjoy
}
```

動物で、遊びが好きな猫

## 動作テスト

```go:テストコード
func main() {
	cat := &Cat{}
	cat.Name = "ボス猫"
	cat.Eat("お菓子")
}
```

```:実行結果
ボス猫はお菓子を食べた
```

CatはEatできた。


# メソッドを乗っ取る　overrideっぽい感じで

```go:追加実装
func (c *Cat) Eat(something string) {
	c.Animal.Eat(something)
	fmt.Println("ニャー by", c.Name)
}
```

```go:テストコード
func main() {
	cat := &Cat{}
	cat.Name = "ボス猫"
	cat.Eat("お菓子")
}
```

```go:実行結果
ボス猫はお菓子を食べたニャー by ボス猫
```

テストコードは変えずに、乗っ取った感じになった。
乗っ取られた後に、拡張元を呼び出す

```go:テストコード
    cat := &Cat{}
    cat.Eat("お菓子")
    cat.Animal.Eat("お菓子")
```

```:実行結果
ボス猫はお菓子を食べたニャー by ボス猫
ボス猫はお菓子を食べた
```

# 別の形で渡す

```go:これはコンパイルエラー
cat := &Cat{}
var a *Animal
a = cat
```

継承では無いのでもちろんダメ。複数実装できるし。
下のように部分的に渡すのはOK

```go:OK
cat := &Cat{}
var a *Animal
a = &cat.Animal
```

インターフェースで渡すのもOK

```go:OK
cat := &Cat{}
var a interface{}
a = cat
```

```go:OK
cat := &Cat{}
var a AnimalAction
a = cat

type AnimalAction interface {
	Eat(somthing string)
}
```

```go:テストコード
	cat := &Cat{}
	cat.Name = "ボス猫"
	var a AnimalAction
	a = cat
	a.Eat("お菓子")
```

```go:実行結果
ボス猫はお菓子を食べたニャー by ボス猫
```

# 実際に機能を拡張してみる

webの処理で使うtemplate.Templateを拡張する

```go:実装例
package mytemplate

import "html/template"

type Template struct {
	*template.Template
}

func Must(t *template.Template, err error) *Template {
	temp := template.Must(t, err)
	return &Template{
		Template: temp,
	}
}
```

紛らわしいけど「Template」は拡張したもの。
同じ名前にしておくと後々便利。 `import template "mytemplate"`って書くと入れ替わるし。
「template.Template」は拡張前のもの。

```go:利用例（拡張前）
tm := template.Must(template.ParseFiles("templates/" + filename))
```

```go:利用例（拡張後）
tm := mytemplate.Must(template.ParseFiles("templates/" + filename))
```

自分の構造体に持ってこれたので、後は自由。

毎回、同じデータをテンプレートに渡す機能を実装してみる

```go:拡張例
func (t *Template) Execute(wr io.Writer, data map[string]interface{}) error {
	data["stylesheet"] = template.HTML(`<link rel="stylesheet" type="text/css" href="semantic.min.css">`)
	return t.Template.Execute(wr, data)
}
```

```go:利用例（拡張前）
tm := template.Must(template.ParseFiles("templates/" + filename))
tm.Execute(w, map[string]interface{}{
	"list": list,
})
```

```go:利用例（拡張後）
tm := mytemplate.Must(template.ParseFiles("templates/" + filename))
tm.Execute(w, map[string]interface{}{
	"list": list,
})
```

もちろん、他のメソッドはそのまま利用可能。
パッケージ名を入れ替えるだけで実装を変えられる。（紛らわしさも残るが）
継承では無いけど、機能を引き継いで拡張できた。


# 機能の引き継ぎとは関係なくなる

一応ビルドは通る。
ただし、実行時に怒られるパターン。

```go:実行例
type Cat struct {
	AnimalAction // ここをインターフェースに変えた
}
type AnimalAction interface {
	Eat(somthing string)
}
func main() {
	cat := &Cat{}
	cat.Eat("お菓子")
}
```


```:実行結果
panic: runtime error: invalid memory address or nil pointer dereference
```

結局interfaceという受け皿を用意しているだけで何も入っていないから、ビルドは通るけど設定していないという事。
この方法を使うと、Eatの実装が気分次第で入れ替え可能。

```go:追加実装例
type ActionHungry struct {
}

func (*ActionHungry) Eat(somthing string) {
	fmt.Println(somthing, "を食べた")
}

type ActionFull struct {
}

func (*ActionFull) Eat(somthing string) {
	fmt.Println(somthing,"を食べなかった")
}
```

```go:動作テスト
func main() {
	cat := &Cat{}
	cat.AnimalAction = &ActionHungry{}
	cat.Eat("お菓子")
	cat.AnimalAction = &ActionFull{}
	cat.Eat("お菓子")
}
```

```:実行結果
お菓子 を食べた
お菓子 を食べなかった
```

cat.Eat()の挙動が変わった。
単に普通のインターフェース使った実装に変わっただけ。引き継いでない。