【Goのやさしい記事】埋め込みによる委譲を5分で学ぼう

# はじめに
12/1から3日連続で、Go初心者向けのやさしい記事を公開しています。
今日のテーマは委譲です。

「Goには継承がないけど委譲があるよ。」と言われて、「委譲って何？！」と思われた人向けに、なるべく簡潔に分かりやすくまとめました。

インターフェースの基本理解が必要なため、自信のない方は前日のアドベントカレンダーに投稿した[【Go初心者向けのやさしい記事】Goのインターフェースを10分で学ぼう](https://qiita.com/gold-kou/private/fdecea86fbe65e65160a)を見てください。

![zozo.go](https://gyazo.com/edf4b24a694f36f83e1a4e6a7f865367.png)

# 委譲と埋め込み
## 委譲とは
委譲とは、ある構造体やインターフェースの機能を別の構造体やインターフェースでも使えるようにする手法です。
メソッドやフィールドの再利用性を高めます。

Goにはクラスが存在せず、構造体がクラスに似た働きをしています。
しかしながら、構造体はクラスではないため継承ができません。
代わりに、「埋め込み」を利用して委譲ができます。
埋め込みとは、別の構造体やインターフェースを入れ子にしてそれらを要素として持つことです。

## 委譲の実装例
### 構造体に構造体を埋め込む
一番使うパターンかと思います。
構造体に構造体を埋め込むことで、別の構造体のフィールドやメソッドをそのまま使えます。

下の実装例では、構造体Aが構造体Bに埋め込まれており、構造体Bは構造体AのフィールドfieldAやメソッドHogeを扱うことができます。

```go
type SampleStructA struct {
	fieldA string
}

func (a *SampleStructA) Hoge() string {
	return "hoge"
}

type SampleStructB struct {
	SampleStructA
	fieldB string
}

func main() {
	a := &SampleStructA{fieldA: "aaa"}
	b := &SampleStructB{SampleStructA{fieldA: "aaa"}, "bbb"}
	fmt.Println(a) // &{aaa}
	fmt.Println(b) // &{{aaa} bbb}
	fmt.Println(b.Hoge()) // hoge
}
```

### インターフェースにインターフェースを埋め込む
インターフェースにインターフェースを埋め込むことで、インターフェースを階層関係でまとめることができます。

下の実装例では、インターフェースAとBはインターフェースCに埋め込まれています。
構造体DはAとBのメソッドをどちらも実装しているため、インターフェースAとBとCを全て満たしています。

```go
type SampleInterfaceA interface {
	Hoge()
}

type SampleInterfaceB interface {
	Fuga()
}

type SampleInterfaceC interface {
	SampleInterfaceA
	SampleInterfaceB
}

type SampleStructD struct {
}

func (d *SampleStructD) Hoge() string {
	return "hoge"
}

func (d *SampleStructD) Fuga() string {
	return "fuga"
}

func main() {
	d := SampleStructD{}
	fmt.Println(d.Hoge()) // hoge
	fmt.Println(d.Fuga()) // fuga
}
```

### 構造体にインターフェースを埋め込む
構造体にインターフェースを埋め込むことで、構造体はインターフェースで宣言されたメソッドをオーバーライドできます。

下の実装例では、SampleStructBにSampleInterfaceAを埋め込んでいるため、SampleStructBはメソッドHogeをオーバーライドできます。
もちろん、SampleStructAはSampleInterfaceAを満たしているため、SampleStructAもメソッドHogeを実行できます。

```go
type SampleInterfaceA interface {
	Hoge() string
}

type SampleStructA struct {
}

func (a *SampleStructA) Hoge() string {
	return "hoge"
}

type SampleStructB struct {
	SampleInterfaceA
}

func (b *SampleStructB) Hoge() string {
	return "hoge!!!"
}

func main() {
	a := SampleStructA{}
	fmt.Println(a.Hoge()) // hoge
	b := SampleStructB{}
	fmt.Println(b.Hoge()) // hoge!!!
}
```

### インターフェースを満たすの連鎖
あるインターフェースを満たす構造体を埋め込んだ場合、埋め込んだ構造体もそのインターフェースを満たすことになります。

下の実装例では、SampleInterfaceAを満たすSampleStructAを埋め込んだSampleStructBは、SampleInterfaceAを満たすことにもなります。
したがって、SampleStructBはSampleStructAのHoge()メソッドを実行できます。

```go
type SampleInterfaceA interface {
	Hoge() string
}

type SampleStructA struct {
}

func (a *SampleStructA) Hoge() string {
	return "hoge"
}

type SampleStructB struct {
	SampleStructA
}

func main() {
	a := &SampleStructA{}
	fmt.Println(a.Hoge()) // hoge
	b := &SampleStructB{}
	fmt.Println(b.Hoge()) // hoge
}
```

### 多重委譲
1つの構造体やインターフェースに複数の構造体やインターフェースを埋め込むことが可能です。

下の実装例では、SampleStructCがSampleStructAとSampleStructBを両方埋め込んでいます。
したがって、SampleStructCは、SampleStructAとSampleStructBのフィールド両方にアクセスができます。

```go
type SampleInterfaceA interface {
	Hoge() string
}

type SampleStructA struct {
	hoge string
}

type SampleStructB struct {
	fuga string
}

type SampleStructC struct {
	SampleStructA
	SampleStructB
}

func main() {
	c := &SampleStructC{}
	c.hoge = "hoge"
	c.fuga = "fuga"
	fmt.Println(c.hoge) // hoge
	fmt.Println(c.fuga) // fuga
}
```

https://horizoon.jp/post/2019/03/16/go_embedded_interface/

# まとめ
- 継承の代わりに「埋め込み」を使って委譲ができるよー
- 埋め込みは単なる構造体やインターフェースの入れ子だよー
- 委譲することでメソッドやフィールドを再利用しやすくできるよー

# 参考
- [Goのinterface/structの埋め込み](https://www.sambaiz.net/article/50/)
- [【Go言語】埋め込みでinterfaceを簡単に満たす](https://medium.com/eureka-engineering/golang-embedded-ac43201cf772)