Best practice for overriding methods

5,311 views
Skip to first unread message

Wink Saville

unread,
Oct 30, 2011, 1:06:06 PM10/30/11
to golan...@googlegroups.com
What is the best practice for allowing a child struct to override
methods in a parent struct? This is what I came up with using
an embedded interface:

$ cat embed
package main

import (
    "fmt"
)

// An interface
type FI interface {
    F()
}

// A parent with a default implementation of FI
type parent struct {
FI
}
func (s *parent) F() {
fmt.Printf("parent.F()\n");
}
func (s *parent) doit() {
s.FI.F()
}
func NewParent() (rv * parent) {
rv = new(parent)
rv.FI = rv
return
}

// A child1 with a different FI 
type child1 struct {
parent // Anonymous parent struct to get default implementations
}
func (s *child1) F() {
fmt.Printf("child1.F()\n");
}
func NewChild1() * child1 {
c := new(child1)
c.FI = c
return c
}

// A child2 with default FI
type child2 struct {
parent // Anonymous parent struct to get default implementations
j int
}
func NewChild2() * child2 {
c := new(child2)
c.FI = c
c.j = 3
return c
}

func main() {
p := NewParent()
c1 := NewChild1()
c2 := NewChild2()
p.doit()
c1.doit()
c2.doit()
}

Then executing embed:

$ ./embed 
parent.F()
child1.F()
parent.F()

John Asmuth

unread,
Oct 30, 2011, 1:39:34 PM10/30/11
to golan...@googlegroups.com
*IF* I really needed to do an inheritance/polymorphism model, and I would go through great lengths not to, this is how I would do it.

Jon Bodner

unread,
Oct 31, 2011, 12:14:02 AM10/31/11
to golang-nuts
I've been experimenting with a variation on this idea, using
"abstract" base classes or mixins to provide common generic
functionality. For example, here's one that's based on the concept of
Ruby's Comparable mixin:

http://go-playground.appspot.com/p/kKX729JdEA

Is there a more idiomatic Go way to accomplish this? It's very
concise to define new types that are Comparable.

John Beshir

unread,
Oct 31, 2011, 12:29:22 AM10/31/11
to golan...@googlegroups.com
On 31/10/11 04:14, Jon Bodner wrote:
> I've been experimenting with a variation on this idea, using
> "abstract" base classes or mixins to provide common generic
> functionality. For example, here's one that's based on the concept of
> Ruby's Comparable mixin:
>
> http://go-playground.appspot.com/p/kKX729JdEA
>
> Is there a more idiomatic Go way to accomplish this? It's very
> concise to define new types that are Comparable.

In this example, you could simplify things by replacing ComparableMixin,
BaseComparableMixin, and their methods, with a set of functions taking
two types meeting Comparable.

You then just need to implement LeEqGt() (although I think the name
could be made clearer) on all the types you want it on. No need to embed
anything.

I think this is much simpler. Functions are not second class in Go, and
are a very straightforward way to provide "generic" functionality
operating on an interface.

Kyle Lemons

unread,
Oct 31, 2011, 10:16:08 AM10/31/11
to John Beshir, golan...@googlegroups.com
As has been suggested, I tend to find that designs requiring such thinking usually have some other not-Go-like principles roaming around somewhere that seem to make that a good solution.  A similar but more interesting (and more Go-like, I think) way to do something similar to solve some classes of these problems is something like this:

type Chef interface {
  Spam() Food
  Eggs() Food
}

type Kitchen struct {
  Chef
}

func (k Kitchen) SpamAndEggs() Food {
  return k.Eggs().With(k.Spam())
}

Basically, if you have some basic set of functionality required to perform an operation but you want to have a single place where you put the code that performs the operation, you can use an interface embedded in your struct and wrap the higher level functionality around it.  My project uses this in a specialized logging package, where the classic log levels and all of their helper formatted/closure helpers are implemented in a struct which embeds an interface with two methods (Log and Logf) so that you can plug any old backend you want (including a mock for testing!) into it without having to write tons of helper functions.  Definitely not helpful in all cases, but something interesting to consider if you find yourself resorting to overriding.
Reply all
Reply to author
Forward
0 new messages