进行虚拟功能仿真

Is there exists some trick to implement virtual functions behaviour in go ? I have the following example.

package main

import "fmt"

type A struct {
}

type B struct {
*A
}

func (this *A) Do() {
    fmt.Println("IM DO")
    this.DoVirtual()
}

func (this *A) DoVirtual() {
    fmt.Println("IM DoVirtual Default implementation")
}

func (this *B) DoVirtual() {
    fmt.Println("IM DoVirtual B implementation")
}

func main() {
    a := &A{}
    a.Do()
    fmt.Println("----")
    b := &B{}
    b.DoVirtual()
    b.Do() // How to make here B.DoVirtual call
}

And the last Do() call uses also default DoVirtual implementation what is actually not was I want. The reason why is it so is go lang iheritance model : this *B and this *A are different pointers in this case, but I wonder is it possible to make some simulation of such behaviour that DoVirtual in last call will be used from B class.

By the time the compiler has selected func (this *A) Do() { the enclosing B is gone, no longer accessible. Go does not support the is-a construct, only the has-a (composition). If one implements a func (this *B) Do() { it will supersede the Do() on *A. Of course, that's not really what you are wanting.

I think the best explanation of the implementation and motivation is here Less is exponentially more from Rob Pike.

my simple simulation, you can improve it with some reflect, code generation or even RPC. the main idea is add a virtual method table, and do dispatch yourself, just like c++ does.

package main

import "fmt"

type A struct {
virFunDispatcher func(funAndParams ... interface{})
}

func newA() *A{
    return &A{func(funAndParams ... interface{}){
        fun := funAndParams[0].(string)
        switch(fun){
            case "DoVirtual":
                fmt.Println("IM DoVirtual Default implementation")
        }
    }}
}

type B struct {
*A
}


func newB() *B{
    a := A{func(funAndParams ... interface{}){
        fun := funAndParams[0].(string)
        switch(fun){
            case "DoVirtual":
                fmt.Println("IM DoVirtual B implementation")
        }
    }}
    return &B{&a}
}

func (this *A) Do() {
    fmt.Println("IM DO")
    this.virFunDispatcher("DoVirtual")
}

func (this *A) DoVirtual() {
    fmt.Println("IM DoVirtual Default implementation")
}

func (this *B) DoVirtual() {
    fmt.Println("IM DoVirtual B implementation")
}

func main() {
    a := newA()
    a.Do()
    fmt.Println("----")
    b := newB()
    b.DoVirtual()
    b.Do() // How to make here B.DoVirtual call
}

https://play.golang.org/p/Iw30lVOhuC