golangでoverrideを実現するためには
golangは継承がない言語ではありますが、メソッドのオーバーライドを行うことができます。
embedded使います。 本来はinterface定義して解決した方がいいんですけども、使っているパッケージでinterface定義されていないやつのMock作るとき等、これで解決しないといけなさそうなケースがありました(´・ω・`)
// embeddedされる側 type BaseModel struct { Name string } func (b *BaseModel) Talk() string { return fmt.Sprintf("name is %s", b.Name) } func (b *BaseModel) Action(in string) string { return fmt.Sprintf("%s, actively %s.", b.Talk(), in) } func NewBaseModel(name string) *BaseModel { return &BaseModel{ Name: name, } } // embeddedする側 type ModelA struct { BaseModel ActionName string } // Actionだけ定義してBase側を上書きする func (m *ModelA) Action(in string) string { return fmt.Sprintf("%s, %s %s.", m.Talk(), m.ActionName, in) } func NewModelA(name, action string) *ModelA { model := &ModelA{ BaseModel: *NewBaseModel(name), ActionName: action, } return model }
な定義があったとして、
package main import "fmt" func main() { dog := NewBaseModel("bog") fmt.Println(dog.Action("run")) cat := NewModelA("cat", "selfishness") fmt.Println(cat.Action("run")) }
で動かす。
name is bog, actively run. name is cat, selfishness run.
期待通りの動作はする。うーん、単純なものならこれで動くのか。
例えば、外部にリクエスト投げるモジュールがあったとして、そいつの送信部分だけ外部に送らないようにする処理で上書きしてやれば、Mock化が簡単にできそうな気がします。
ただ、上記で上書きしきれないパターンがある
今仕事でやってるFirestoreの実送信部分。上書きしたはずが、上書き元が呼ばれてしまうんですよね。
直接オブジェクト作ったところで呼ぶ分には期待通り動きそうですが、メソッドのレシーバーでembedded元が指定されているとそっち呼んでしまうのかな(´・ω・`)あとで検証しますか
多分この[メソッド定義とメソッド呼び出しの真実]あたりが、embedded側が呼ばれる原因なのかもしれません。