Allow using composite as function argument in struct

41 Views Asked by At

Let's say I'm making something like a game engine.

I need an GameObject struct which defines some event handlers:

type GameObject struct {
    transform        Transform
    animatedMesh     AnimatedMesh
    updateHandler    func(self GameObjectGetter)
    onCreateHandler  func(self GameObjectGetter)
    onDestroyHandler func(self GameObjectGetter)
}


func (g GameObject)getGameObject() GameObject {
    return g
 }

 type GameObjectGetter interface {
    getGameObject() GameObject
 }

Then, when I'm initializing some concrete GameObject, I want to define a handler as a custom function:

g.updateHandler = func(self FishGameObject) {  // Error here
    self.tailMotionSpeed = self.boid.acceleration.Normalize().Len()
}

Note here that tailMotionSpeed and boid aren't members of GameObject. They're members of struct FishGameObject which has some custom properties and anonymous GameObject:

type FishGameObject struct {
    leftFinPosition  float32
    rightFinPosition float32
    tailMotionSpeed  float32
    boid             Boid
    GameObject
}

I'm getting an error self.tailMotionSpeed undefined (type GameObjectGetter has no field or method tailMotionSpeed) if I specify argument as GameObjectGetter, and also I'm getting an error cannot use handler (variable of type func(self FishGameObject)) as func(self GameObjectGetter) value in struct literal if I specify argument as FishGameObject. What do I do?

1

There are 1 best solutions below

2
Burak Serdar On BEST ANSWER

What you are trying to do is not possible in Go in the way you are trying to do. However, you can do this:

Define GameObject as an interface:

type GameObject interface {
   GetTransform() *Transform
   GetAnimatedMesh() *AnimatedMesh
   SetUpdateHandler(func(GameObject))
   UpdateHandler() func(GameObject)
   ...
}

The you can define a BaseGameObject:

type BaseGameObject struct {
    transform        Transform
    animatedMesh     AnimatedMesh
    updateHandler    func(GameObject)
    onCreateHandler  func(GameObject)
    onDestroyHandler func(GameObject) 
}

Define all the methods so BaseGameObject is a GameObject.

Then, define FishGameObject as you did, but

fish.SetUpdateHandler(func(self GameObject) {  
    fish:=self.(*FishGameObject)
     ...
   })

You also should use pointer receivers for all the methods.