Go で継承みたいなことをしたい時は Embedded のしくみを使える。ふわっとしかわかってないことに気づいたけど、リファレンスレベルだけど、自分用に整理しておく
Embedded が使える種類
interface と struct に対して使える。
interface
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte)(n int, err error)
type ReadWriter interface {
Reader
Writer
}
struct
struct の場合は、ポインタで書くこと
embeded should be pointer
type ReadWriter struct {
*bufio.Reader
*bufio.Writer
}
struct の初期化
struct の Embedded を使ったら初期化しないといけない。
type Job struct {
Common string
*log.Logger
}
というEmbeddedを持っているとき初期化の際には初期化してEmbedded を持たせてあげる必要がある。
func NewJob(command string, logger *log.Logger) *Job {
return &Job{command, logger}
}
or
job := &Job{command, log.New(os.Stderr, "Job: ", log.Ldate)}
struct のオーバーライド
Embedded を次のようにも書ける。その際には、自分でデリゲートしてあげる必要がある。おそらくメソッドをオーバーライドしたい時に使える。
func (job *Job) Logf(format string, args ...interface{}) {
job.Logger.Logf("%q: %s", job.Command, fmt.Sprintf(format, args...))
}
また、自分で次のように書いてオーバーライドしても良い
type ReadWriter struct {
reader *bufio.Reader
}
func (rw *ReadWriter) Read(p []byte) (n int, err error) {
return rw.reader.Read(p)
}
関数が重複したら?
Embedded を使った Struct と元の struct の関数のシグネチャが重複したら、Embedded を使った方が優先させる。(Job と Logger では、Job の関数が優先)また、Embedded した元の struct で誰かが重複させてしまった場合、その場合でも、Job の方はプロテクションの機構が働いて、使えはする。その重複しているメンバにアクセスしない限りは。
まとめ
リファレンスのまんまですが、自分の整理のために書きました。