我正在玩制作斐波那契堆。 (我在算法类中多次提到它们,我想检查它们。)我希望堆使用任何类型的节点,所以我定义了一个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中做我想要的?接口可以引用自己吗?
答案 0 :(得分:6)
功能
func (e Element) Less(f Element) bool
与界面
中的功能不匹配func Less(other Node) bool
您需要实际匹配签名,如
func (e Element) Less(f Node) bool
是的,这意味着你可以传递一个不是Node
的{{1}}。你必须在运行时和恐慌时测试它。
作为一个例子,为什么会这样,考虑你的代码是否合法,我尝试了以下内容:
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
类型的var中,所以我现在可以使用不是另一个Node
的参数调用Less()
,这违反了该类型Element
。这就是为什么这不合法。