Go言語で手動オブジェクト指向
仮想関数をインターフェースに書き出して、Self経由で呼び出す方式。
手順は、
- 構造体とインターフェースを対にして作る
- それぞれに埋め込みで継承していく
- コンストラクタ関数で、Selfを伝搬させていく
こんなダサくて効率の悪いことは普通やらないが、GUIフレームワークのようにオブジェクト指向が合うものには、部分的に似たような構造が使われている感じがする。
package main import ( "fmt" ) type IA interface { MethodA() } type A struct { Self IA } func (a *A) MethodA() { fmt.Println("A.MethodA") } func (a *A) CallMethodA() { fmt.Println("A.CallMethodA") a.Self.MethodA() // Self経由で呼び出す } func NewA(self IA) *A { a := &A{} if self != nil { a.Self = self } else { a.Self = a } return a } type IB interface { IA MethodB() } type B struct { *A Self IB Super IA } func (b *B) MethodA() { fmt.Println("B.MethodA") b.Super.MethodA() } func (b *B) MethodB() { fmt.Println("B.MethodB") } func NewB(self IB) *B { b := &B{} if self != nil { b.Self = self } else { b.Self = b } b.A = NewA(b.Self) b.Super = b.A return b } type IC interface { IB } type C struct { *B Self IC Super IB } func (c *C) MethodB() { fmt.Println("C.MethodB") } func NewC(self IC) *C { c := &C{} if self != nil { c.Self = self } else { c.Self = c } c.B = NewB(c.Self) c.Super = c.B return c } type ID interface { IC } type D struct { *C Self ID Super IC } func (d *D) MethodA() { fmt.Println("D.MethodA") d.Super.MethodA() } func NewD(self ID) *D { d := &D{} if self != nil { d.Self = self } else { d.Self = d } d.C = NewC(d.Self) d.Super = d.C return d } func main() { d := NewD(nil) d.MethodA() // D.MethodA // B.MethodA // A.MethodA d.CallMethodA() // A.CallMethodA // D.MethodA // B.MethodA // A.MethodA d.MethodB() // C.MethodB }