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

As you wrote, what Go has is not really inheritance, the method that allows inheritance like features is called Embedding.

http://golang.org/doc/effective_go.html#embedding

What it means basically is that the embedded struct has no idea that it is embedded, so you cannot override anything that is called from it. You can actually take the embedded struct and take a reference for it only from the embedding struct.

So your best way to do it is more or less like your second example - through some sort of dependency injection using interfaces. i.e - A has a reference to some interface that does the actual work, say worker, that writes to a file or whatever. Then when instantiating B, you also replace A's worker with another worker (you can do it even without embedding A of course). The A just does something like myWorker.Work() without caring what worker it is.


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


Recently I have a need to do this and the composition method proposed by OP works great.

I try to create another example to try to demonstrate the parent and child relationship and make it easier to read.

https://play.golang.org/p/9EmWhpyjHf:

package main

import (
    "fmt"
    "log"
)

type FruitType interface {
    Wash() FruitType
    Eat() string
}

type Fruit struct {
    name  string
    dirty bool
    fruit FruitType
}

func (f *Fruit) Wash() FruitType {
    f.dirty = false
    if f.fruit != nil {
        return f.fruit
    }
    return f
}
func (f *Fruit) Eat() string {
    if f.dirty {
        return fmt.Sprintf("The %s is dirty, wash it first!", f.name)
    }
    return fmt.Sprintf("%s is so delicious!", f.name)
}

type Orange struct {
    *Fruit
}

func NewOrange() *Orange {
    ft := &Orange{&Fruit{"Orange", true, nil}}
    ft.fruit = ft
    return ft
}
func NewApple() *Fruit {
    ft := &Fruit{"apple", true, nil}
    return ft
}

func (o *Orange) Eat() string {
    return "The orange is so sour!"
}

func main() {
    log.Println(NewApple().Eat())
    log.Println(NewApple().Wash().Eat())
    log.Println(NewOrange().Eat())
    log.Println(NewOrange().Wash().Eat())
}