4

我正在制作一个斐波那契堆。(在我正在学习的算法类中多次提到它们,我想检查它们。)我希望堆使用任何类型的节点,所以我定义了一个 Node 接口:

package node

type Node interface {
    AddChild(other Node)
    Less(other Node) bool
}

type NodeList []Node

func (n NodeList) AddNode(a Node) {
    n = append(n, a)
}

(我使用 []Node 数组,因为它与堆定义具有相同的效果。)如您所见,Node 接口使用 Node 类型的参数定义了它的两个函数。这应该意味着函数必须接受实现 Node 接口的参数。堆的其余部分使用这些节点。

在使用这个堆的程序中,我创建了一个实现 Node 接口的类型:

package main

import "container/list"
import node "./node"

type Element struct {
    Children *list.List
    Value int
}

func (e Element) AddChild(f Element) {
    e.Children.PushBack(f)
}

func (e Element) Less(f Element) bool {
    return e.Value < f.Value
}

func main() {
    a := Element{list.New(), 1}

    n := new(node.NodeList)
    n.AddNode(a)
}

然而,这并没有奏效。编译器抱怨 Element 没有正确的接口函数定义。

cannot use a (type Element) as type node.Node in function argument:
Element does not implement node.Node (wrong type for AddChild method)
    have AddChild(Element)
    want AddChild(node.Node)

这里有什么问题?显然 Element 没有正确实现接口,但我认为这是因为我如何定义接口。有没有正确的方法可以在 Go 中做我想做的事情?接口可以引用自己吗?

4

1 回答 1

6

功能

func (e Element) Less(f Element) bool

与界面中的功能不匹配

func Less(other Node) bool

您需要实际匹配签名,如

func (e Element) Less(f Node) bool

是的,这意味着您可以通过 aNode不是Element. 您必须在运行时对此进行测试并惊慌失措。


作为一个为什么会这样的例子,考虑你的代码是否合法,我尝试了以下方法:

type Other int
func (o Other) Less(f Other) bool {
    return o < f
}
func (o Other) AddChild(f Other) {}
e = GetSomeElement() // of type Element
var o Other
var n Node = e
fmt.Println(n.Less(o))

因为我将 存储Element到 type 的 var 中Node,所以我现在可以Less()使用不是 another 的参数调用Element,这违反了 的类型Element.Less()。这就是为什么这是不合法的。

于 2012-11-08T01:45:10.970 回答