理解がなんとなく浅いと感じていたGolangの抽象化について簡単にまとめました。
goのサンプル
package main import "fmt" type Stringer interface { String() string } // Stringerを実装する type Hex int func (h Hex) String() string { return fmt.Sprintf("%x", int(h)) } func main() { var s Stringer h := Hex(100) s = h // Stringer に Hexを埋め込む fmt.Println(h.String()) // Hexに定義されているString() fmt.Println(s.String()) // Stringerに定義されているString() }
Stringer
はinterface型でstring
型の返り値を持つString()
メソッドを持つ。- 'Hex' は int型の新しいtypeとして定義されている。
Hex
はstring
型の返り値を持つString()
メソッドを持つ。- 変数
s
はString()
の実装の詳細を定義していなくても、Hex
で定義されているString()
の実装と同じふるまいをできる。
同じinterfaceを持つtypeで新しく定義した型は同じメソッドを持つ場合、実装の詳細をinterface型で定義している方に埋め込むことで、埋め込まれた側(ここでは Stringer
型)は Hex
で定義されている実装の詳細を埋め込まれることで使うことができるようになる。
interface型を使うことで抽象化を実現できる。
というのがいまいち理解できなかったのですが、
type Hex int func (h Hex) String() string{ // String()の実装の詳細 }
としている箇所で Hex
に対して String()
メソッドを定義しているときに
type Hex int { String() string }
と見ることができるので、
type Stringer interface { String() string }
こう考えると埋め込むことでメソッド名と返り値が同じメソッドを持つ構造体の場合、実装の詳細も埋め込むことができる。
ということなのかなと。