英文:
Go Interfaces that use the interface in the definition
问题
我正在尝试创建一个斐波那契堆。 (在我正在学习的算法课程中多次提到它们,我想要了解一下。)我希望堆使用任意类型的节点,因此我定义了一个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中是否有正确的方法可以实现我想要的功能?接口可以引用自身吗?
英文:
I am playing around with making a Fibonacci Heap. (They are mentioned several times in an algorithms class that I'm taking, and I want to check them out.) I want the heap to use nodes of any kind, so I define a Node interface:
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)
}
(I use the []Node array because it has the same affect as the heap definition.) As you can see, the Node interface defines its two functions with arguments of type Node. This should mean that the functions have to accept arguments that implement the Node interface. The rest of the heap uses these nodes.
In the program that uses this heap, I make a type that implements the Node interface:
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)
}
However, this didn't work. The compiler complains that Element doesn't have the correct function definitions for the interface.
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)
What is wrong here? Obviously Element doesn't implement the interface correctly, but I think it's because of how I defined the interface. Is there a correct way to do what I want in Go? Can interfaces refer to themselves?
答案1
得分: 6
The function
func (e Element) Less(f Element) bool
does not match the function from the interface
func Less(other Node) bool
You need to actually match the signature, as in
func (e Element) Less(f Node) bool
And yes, this means you could be passed a Node
that isn't an Element
. You'll have to test for that at runtime and panic.
As an example for why this is so, consider if your code was legit, and I tried the following:
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))
Because I stored the Element
into a var of type Node
, I can now call Less()
with an argument that isn't another Element
, which violates the type of Element.Less()
. This is why that's not legal.
英文:
The function
func (e Element) Less(f Element) bool
does not match the function from the interface
func Less(other Node) bool
You need to actually match the signature, as in
func (e Element) Less(f Node) bool
And yes, this means you could be passed a Node
that isn't an Element
. You'll have to test for that at runtime and panic.
As an example for why this is so, consider if your code was legit, and I tried the following:
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))
Because I stored the Element
into a var of type Node
, I can now call Less()
with an argument that isn't another Element
, which violates the type of Element.Less()
. This is why that's not legal.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论