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
}