I am looking to translate a "classic OO" example into Go, one in which a set of subclasses implement some methods on their own but they share an implementation of some methods via their superclass. I'm well aware of how to use Go's interfaces and I've even used embedding, but I'm not quite sure what, if any, idioms to employ to capture this intended behavior.
Here's a concrete, and probably a very familiar example. I'll use Ruby. There are two kinds of animals, dogs and cows. All animals have a name and they can speak. The way you set and get the same is the same regardless of the animal type; the sound they make differs depending on the subclass. Now there is a speak
method which is the same for all animals, but it delegates to the subclass's sound
method. Here it is in Ruby:
class Animal
def initialize(name); @name = name; end
def speak; puts "#{@name} says #{sound()}"; end
end
class Dog < Animal; def sound(); "woof"; end; end
class Cow < Animal; def sound(); "mooo"; end; end
How is this best captured in Go?
So far I've tried
type Animal struct {
name string
}
type Cow struct {
Animal
}
type Dog struct {
Animal
}
and I've been able to construct "animals" like so:
func (d Dog) sound() string {return "woof"}
func (c Cow) sound() string {return "mooo"}
func main() {
d := Dog{Animal{"Sparky"}}
c := Cow{Animal{"Bessie"}}
fmt.Println(d.name)
fmt.Println(c.sound())
}
But I feel I'm going about this all wrong. I know I can put sound()
in an interface, but then the specific animals are sounders, not really animals. If Animal
becomes the interface, I can't share the name and the speak code. I realize the designers of Go went with interfaces-only and chose not do directly support this classic OO use case the way we would see it done in Ruby, Python, Java, and so on, but I suspect there should be some idiom or best practice for simulating this. What is the preferred way of doing so?