I have to periodically call a method of a parent struct but when called, it must update extended properties unique to the embedded struct (in my case the structs have different id data types).
The only solution I could think of was to override the a method of the parent struct so that, when the periodic method is called again, it uses the method of the embedded struct instead of the parent's original.
The code looks as follows:
package main
import (
"fmt"
)
type Fruit struct {
image *Image
tree *Tree
SetImage func(*Image)
SetTree func(*Tree) // #2 (always nil for Strawberry)
}
func NewFruit() *Fruit {
f := &Fruit{}
f.SetImage = f.setImage
f.SetTree = f.setTree
return f
}
func (f *Fruit) Image() *Image {
return f.image
}
func (f *Fruit) Tree() *Tree {
return f.tree
}
func (f *Fruit) setImage(i *Image) {
f.image = i
}
func (f *Fruit) setTree(t *Tree) {
f.tree = t
}
type Strawberry struct {
*Fruit
id int
}
func NewStrawberry(f *Fruit) *Strawberry {
strawberry := &Strawberry{Fruit: f}
return strawberry
}
func (s *Strawberry) SetID(i int) {
s.id = i
}
func (s *Strawberry) ID() int {
return s.id
}
func (s *Strawberry) setImage(i *Image) {
s.id = 6
s.image = i
}
type Kiwi struct {
*Fruit
id string
}
func NewKiwi(f *Fruit) *Kiwi {
kiwi := &Kiwi{Fruit: f}
return kiwi
}
func (k *Kiwi) SetID(i string) {
k.id = i
}
func (k *Kiwi) ID() string {
return k.id
}
func (k *Kiwi) setImage(i *Image) {
k.id = "abc"
k.image = i
}
func (k *Kiwi) setTree(t *Tree) {
k.tree = t
}
type Image struct {
path string
}
type Tree struct {
height int
}
func main() {
f := NewFruit()
f.SetImage(&Image{"kiwi1.jpg"})
/*s := NewStrawberry(f)
s.SetImage = s.setImage
fmt.Println(s, s.ID(), s.Image())
f.SetImage(&Image{"strawberry.jpg"})
fmt.Println(s, s.ID(), s.Image())*/
k := NewKiwi(f)
k.SetImage = k.setImage
k.SetTree = k.setTree
fmt.Println(k, k.ID(), k.Image())
f.SetImage(&Image{"kiwi2.jpg"})
f.SetTree(&Tree{2})
fmt.Println(k, k.ID(), k.Image(), k.Tree())
}
While the above code does work, I have two concerns when the parent struct Fruit
needs eg. 10 additional properties with their required SetXXX(*XXX)
methods:
Then all the embedded structs has to be updated to reflect the new parent struct methods. Which seems like a lot of necessary coding per property.
Some of these embedded structs will not need all of the property methods, leaving a few nil
. A good example being not all fruit grow on trees. Leaving property at comment #2
useless for Strawberry
.
Are both these concerns valid and is there a way I can avoid them?
P.S.
The application requires a lot of operational throughput so ideally the code should be type safe and optimal without the use of reflection and the overuse of type assertion (can't make every property interface{}
).
Are both these concerns valid and is there a way I can avoid them?
No and yes.
Just write idiomatic GO and do not try to write traditional OO in Go. E.g. Setters and Getters are not common in Go. And stop thinking of embedding as a parent/child relation.