去虚函数模拟

go virtual function simulation

在 go 中是否存在一些实现虚函数行为的技巧?我有以下示例。

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
}

最后一个 Do() 调用也使用默认的 DoVirtual 实现,但实际上不是我想要的。原因是 go lang iheritance 模型:this *B 和 this *A 在这种情况下是不同的指针,但我想知道是否有可能对上次调用中的 DoVirtual 将从 B class。

当编译器选择 func (this *A) Do() { 时,封闭的 B 已经消失,无法再访问。 Go 不支持 is-a 结构,只支持 has-a(组合)。如果实现 func (this *B) Do() { 它将取代 *A 上的 Do()。当然,这不是你真正想要的。

我认为 Rob Pike Less is exponentially more 对实施和动机的最佳解释。

我的简单模拟,你可以用一些reflect、代码生成甚至RPC来改进它。主要思想是添加一个虚拟方法 table,然后像 C++ 一样自己分派。

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