donglaoping9702 2017-12-11 17:41
浏览 228
已采纳

从Golang的父级实现方法中调用子级方法

I'm trying to implement a behavior tree in go, and I'm struggling with its composition features. Basically, I need Tick() implemented below to call the method defined by wherever it was embedded.

Here is behavior.go:

type IBehavior interface {
  Tick() Status
  Update() Status
}

type Behavior struct {
  Status Status
}

func (n *Behavior) Tick() Status {
  fmt.Println("ticking!")
  if n.Status != RUNNING { n.Initialize() }
  status := n.Update()
  if n.Status != RUNNING { n.Terminate(status) }

  return status
}

func (n *Behavior) Update() Status {
  fmt.Println("This update is being called")
  return n.Status
}

And here is the Behavior struct being embedded:

type IBehaviorTree interface {
  IBehavior
}

type BehaviorTree struct {
  Behavior

  Root IBehavior
}

func (n *BehaviorTree) Update() Status {
  fmt.Printf("Tree tick! %#v
", n.Root)
  return n.Root.Tick()
}

A few more files to make this example make sense:

type ILeaf interface {
  IBehavior
}

type Leaf struct {
  Behavior
}

And this one:

type Test struct {
  Leaf

  Status Status
}

func NewTest() *Test {
    return &Test{}
}

func (n Test) Update() Status {
    fmt.Println("Testing!")
    return SUCCESS
}

And here is an example of its usage:

tree := ai.NewBehaviorTree()
test := ai.NewTest()
tree.Root = test

tree.Tick()

I was expecting the tree to tick normally by printing this:

ticking!
Tree tick!

But instead I'm getting:

ticking!
This update is being called

Could anyone help me with this issue?

Edit: Added a few extra files to illuminate the issue. Also, I don't understand the downvotes. I have an honest go question. Am I only supposed to ask questions that make sense to me already?

  • 写回答

2条回答 默认 最新

  • douwei9759 2017-12-11 21:36
    关注

    Your issue here is that Tick() is not defined on your BehaviorTree structure. As a result, when you call tree.Tick(), there's no direct method defined, so it calls the promoted Tick() method of the embedded Behavior struct. That Behavior struct has no idea what a BehaviorTree is! In Go’s embedding style of pseudo-inheritance, “child” types have no concept of their "parents", nor any reference or access to them. Embedded methods are called with the embedded type as their receiver, not the embedding struct.

    If you want your expected behavior, you need to define a Tick() method on your BehaviorTree type, and have that method to call its own Update() method (and then call sub Tick() or Update() methods if you wish). For example:

    type BehaviorTree struct {
      Behavior
    
      Root IBehavior
    }
    
    func (n *BehaviorTree) Tick() Status {
        n.Update() // TODO: do you want this status or the Root.Tick() status?
        return n.Root.Tick()
    }
    
    func (n *BehaviorTree) Update() Status {
      fmt.Printf("Tree tick! %#v
    ", n.Root)
      return nil
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示