I want to implement such code, where B inherit from A and only override A\'s Foo() method, and I hope the code to print B.Foo(), but it still print A.Foo(), it seems that th
Go does not support virtual method overriding. The design pattern you want to use is thus not directly supported by Go. It is considered bad practice because changing the implementation of A.Bar() would break all derived classes like B that assume A.Foo() will be called by A.Bar(). The design pattern you want to use will make your code brittle.
The way to do it in Go would be to define a Fooer interface with a Foo() method. A Fooer would be passed as argument to Bar() or stored in a field of A and called by A.Bar(). To change the Foo action, change the Fooer value. This is called composition, and it is much better than changing Foo action by inheritance and method overriding.
Here is an idiomatic way to do what you want to do in Go: https://play.golang.org/p/jJqXqmNUEHn. In this implementation, the Fooer is a member field of A that is initialized by a parameter of to the instance factory function NewA()
. This design pattern is preferable when the Fooer doesn't change frequently during the lifetime of A. Otherwise, you may pass the Fooer as parameter of the Bar()
method.
This is how we change the behavior of Foo()
in Go. It is called composition because you change the behavior of Bar()
by changing the instances composing A.
package main
import (
"fmt"
)
type Fooer interface {
Foo()
}
type A struct {
f Fooer
}
func (a *A) Bar() {
a.f.Foo()
}
func NewA(f Fooer) *A {
return &A{f: f}
}
type B struct {
}
func (b *B) Foo() {
fmt.Println("B.Foo()")
}
type C struct {
}
func (c *C) Foo() {
fmt.Println("C.Foo()")
}
func main() {
a := NewA(new(B))
a.Bar()
a.f = &C{}
a.Bar()
}
PS: Here is a possible implementation of the design pattern you wanted to implement for documentation purpose: https://play.golang.org/p/HugjIbYbout