golang中父类实现方法调用子类方法

Calling child's method from parent's implementation method in golang

我正在尝试在 go 中实现行为树,但我正在为它的组合功能而苦苦挣扎。基本上,我需要在下面实现 Tick() 来调用嵌入的任何地方定义的方法。

这里是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
}

这是嵌入的 Behavior 结构:

type IBehaviorTree interface {
  IBehavior
}

type BehaviorTree struct {
  Behavior

  Root IBehavior
}

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

更多文件使这个例子有意义:

type ILeaf interface {
  IBehavior
}

type Leaf struct {
  Behavior
}

还有这个:

type Test struct {
  Leaf

  Status Status
}

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

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

下面是它的用法示例:

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

tree.Tick()

我希望通过打印这个树来正常滴答作响:

ticking!
Tree tick!

但我得到的是:

ticking!
This update is being called

谁能帮我解决这个问题?

编辑:添加了一些额外的文件来说明问题。另外,我不明白反对票。我有一个诚实的问题。我应该只问对我来说有意义的问题吗?

正如沃尔克所说

Go has absolutely no notion of inheritance (embedding is not inheritance) and you simply cannot do parent/child stuff in Go. Redesign

据我所知,您想要的是一个使用接口多次执行同一任务的函数。

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

当然Initialize就得在界面里面了。

您的问题是 Tick() 未在您的 BehaviorTree 结构中定义。因此,当您调用 tree.Tick() 时,没有定义直接方法,因此它会调用嵌入式 Behavior 结构的提升的 Tick() 方法。 Behavior struct 不知道 BehaviorTree 是什么! 在 Go 的伪继承嵌入风格中,“子”类型没有它们的概念 "parents",也没有对它们的任何引用或访问。嵌入式方法使用 嵌入式类型 作为它们的接收者调用,而不是嵌入结构。

如果您想要预期的行为,您需要在 BehaviorTree 类型上定义一个 Tick() 方法,并让该方法调用它自己的 Update() 方法(然后调用sub Tick()Update() 方法,如果你愿意的话)。例如:

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", n.Root)
  return nil
}