Go

埋め込んだ構造体のメソッドのレシーバは更新されない

More than 1 year has passed since last update.

Go では構造体の中に構造体を埋め込んで、オブジェクト指向でいう継承っぽいことができます。
そこで、各種処理で共通となるメソッドをベースとなる構造体に埋め込んで、埋め込み先の構造体で派生的な処理をさせることができれば楽かなと思ったができなかった、という話。

具体的には以下のようなコードを想定していました。

package main

import "fmt"

type TypeSwitcher interface {
    TypeSwitch(TypeSwitcher)
}

type A struct{}

// 呼び出し処理は共通
func (a *A) CallTypeSwitch1(ts TypeSwitcher) {
    ts.TypeSwitch(a)
}

func (a *A) CallTypeSwitch2(ts TypeSwitcher) {
    a.TypeSwitch(ts)
}

// 各構造体は好きに TypeSwitch の処理を実装したい
func (a *A) TypeSwitch(ts TypeSwitcher) {
    fmt.Println("not implemented")
}

type B struct{ A }

// 構造体B
func (b *B) TypeSwitch(ts TypeSwitcher) {
    switch ts.(type) {
    case *A:
        fmt.Println("type is A")
    case *B:
        fmt.Println("type is B")
    }
}

func main() {
    b1 := B{}
    b2 := B{}
    b1.CallTypeSwitch1(&b2) // type is A
    b1.CallTypeSwitch2(&b2) // not implemented
}

以上のコードを実行すると、以下のように出力されます。

type is A
not implemented

構造体Aを構造体Bに埋め込んでも、構造体AのメソッドのレシーバがBになることはなく、Aのまま実行されます。
なので、上記コードで実行している CallTypeSwitch メソッドは B構造体から実行されていても A 構造体のメソッドとして実行されます。

個人的に、構造体の埋め込みはついついオブジェクト指向の継承のように考えてしまいますが、実際には違うので注意が必要と思いました。