emahiro/b.log

Drastically Repeat Yourself !!!!

Golangでの抽象化について

理解がなんとなく浅いと感じていた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()
}
  1. Stringer はinterface型で string 型の返り値を持つ String() メソッドを持つ。
  2. ‘Hex’ は int型の新しいtypeとして定義されている。
  3. Hexstring 型の返り値を持つ String() メソッドを持つ。
  4. 変数 sString() の実装の詳細を定義していなくても、 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
}

こう考えると埋め込むことでメソッド名と返り値が同じメソッドを持つ構造体の場合、実装の詳細も埋め込むことができる。

ということなのかなと。