The struct embedding gives a great deal of power. You can effectively inherit data and methods. And override methods.
I think the only case where classical polymorphism falls down is having to explicitly reference the embedded type in non-method calls. Method calls proxy just fine though.
I get that this isn’t “really” an is-a relationship, but it feels close enough to get work done for me.
package main
type A struct {
Name string
}
type B struct {
A
}
func who(a A) {
println("I am", a.Name)
}
func (a A) whoMethod() {
println("As a method, I am", a.Name)
}
func (a A) Shout() {
println("I AM", a.Name)
}
func (b B) Shout() {
// We also have access to the embedded type's implementation if we want it
// via b.A.Shout
println("I SHOUT MY NAME", b.Name)
}
func main() {
a := A{"alice"}
b := B{A{"bob"}}
a.whoMethod()
b.whoMethod() // Calls the inherited method
a.Shout()
b.Shout() // Calls the overridden method
who(a)
who(b.A) // who(b) will fail with a compile-time error
}
The struct embedding gives a great deal of power. You can effectively inherit data and methods. And override methods.
I think the only case where classical polymorphism falls down is having to explicitly reference the embedded type in non-method calls. Method calls proxy just fine though.
I get that this isn’t “really” an is-a relationship, but it feels close enough to get work done for me.