is it possible to call overridden method from parent struct in Golang?

后端 未结 6 1531
攒了一身酷
攒了一身酷 2020-11-27 04:34

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

6条回答
  •  萌比男神i
    2020-11-27 05:17

    Been struggling with this myself. Found 2 solutions:

    1. Idiomatic Go way: implement the common "method" as external function with interface as argument.

       package main
      
       import "fmt"
      
       // Fooer has to Foo
       type Fooer interface {
           Foo()
       }
      
       // Bar is a proxy, that calls Foo of specific instance.
       func Bar(a Fooer) {
           a.Foo()
       }
      
       //////////////////////////////////////////////////////////////////////
       // usage
      
       func main() {
           b := &B{} // note it is a pointer
           // also there's no need to specify values for default-initialized fields.
           Bar(b) // prints: B.Foo()
       }
      
       //////////////////////////////////////////////////////////////////////
       // implementation
      
       // A is a "base class"        
       type A struct {
       }
      
       func (a *A) Foo() {
           fmt.Println("A.Foo()")
       }
      
       // B overrides methods of A
       type B struct {
           A
       }
      
       func (b *B) Foo() {
           fmt.Println("B.Foo()")
       }
      

    Try it on Go Playground: https://play.golang.org/p/2TbmHUs9_Dt

    1. Similar to your second option: interface hackery. However, since Bar() is not specific to A (it is common to A and B), let's move it to base class, and hide implementation details and all dangerous stuff:

       package main
      
       import "fmt"
      
       //////////////////////////////////////////////////////////////////////
       // Usage
      
       func main() {
           b := NewB()
           b.Bar() // prints: B.Foo()
      
           a := NewA()
           a.Bar() // prints: A.Foo()
       }
      
       //////////////////////////////////////////////////////////////////////
       // Implementation.
      
       // aBase is common "ancestor" for A and B.
       type aBase struct {
           ABCD // embed the interface. As it is just a pointer, it has to be initialized!
       }
      
       // Bar is common to A and B.
       func (a *aBase) Bar() {
           a.Foo() // aBase has no method Foo defined, so it calls Foo method of embedded interface.
       }
      
       // a class, not exported
       type a struct {
           aBase
       }
      
       func (a *a) Foo() {
           fmt.Println("A.Foo()")
       }
      
       // b class, not exported
       type b struct {
           aBase
       }
      
       func (b *b) Foo() {
           fmt.Println("B.Foo()")
       }
      
       //////////////////////////////////////////////////////////////////////
       // Now, public functions and methods.
      
       // ABCD describes all exported methods of A and B.
       type ABCD interface {
           Foo()
           Bar()
       }
      
       // NewA returns new struct a
       func NewA() ABCD {
           a := &a{}
           a.ABCD = a
           return a
       }
      
       // NewB returns new struct b
       func NewB() ABCD {
           b := &b{}
           b.ABCD = b
           return b
       }
      

    Try it on Go Playground: https://play.golang.org/p/0Zcs_arturP

提交回复
热议问题