英文:
Make two structs which differ with one method implementation
问题
我想创建一个整数的最小堆和最大堆:
package main
import (
"container/heap"
"fmt"
)
func main() {
hi := make(IntHeap, 0)
for number := 10; number >= 0; number-- {
hi = append(hi, number)
}
heap.Init(&hi)
fmt.Println(heap.Pop(&hi))
fmt.Println(heap.Pop(&hi))
fmt.Println(heap.Pop(&hi))
}
// IntHeap 是一个整数的最小堆。
type IntHeap []int
func (h IntHeap) Len() int { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *IntHeap) Push(x interface{}) {
*h = append(*h, x.(int))
}
func (h *IntHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
type IntMaxHeap IntHeap
func (h IntMaxHeap) Less(i, j int) bool { return h[i] > h[j] }
如果我想使用 IntMaxHeap
替代 IntHeap
,我会得到以下错误:
./median_stream.go:14: cannot use &hi (type *IntMaxHeap) as type heap.Interface in function argument:
*IntMaxHeap does not implement heap.Interface (missing Len method)
./median_stream.go:15: cannot use &hi (type *IntMaxHeap) as type heap.Interface in function argument:
*IntMaxHeap does not implement heap.Interface (missing Len method)
./median_stream.go:16: cannot use &hi (type *IntMaxHeap) as type heap.Interface in function argument:
*IntMaxHeap does not implement heap.Interface (missing Len method)
./median_stream.go:17: cannot use &hi (type *IntMaxHeap) as type heap.Interface in function argument:
*IntMaxHeap does not implement heap.Interface (missing Len method)
我该如何创建两个只有一个方法实现不同的结构体("类")?工作版本应该打印堆中的三个最大数。
英文:
I want to make a min and max heap of integers:
<!-- language: golang -->
package main
import (
"container/heap"
"fmt"
)
func main() {
hi := make(IntHeap, 0)
for number := 10; number >= 0; number-- {
hi = append(hi, number)
}
heap.Init(&hi)
fmt.Println(heap.Pop(&hi))
fmt.Println(heap.Pop(&hi))
fmt.Println(heap.Pop(&hi))
}
// An IntHeap is a min-heap of ints.
type IntHeap []int
func (h IntHeap) Len() int { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *IntHeap) Push(x interface{}) {
*h = append(*h, x.(int))
}
func (h *IntHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
type IntMaxHeap IntHeap
func (h IntMaxHeap) Less(i, j int) bool { return h[i] > h[j] }
If I want to use IntMaxHeap
instead, I am getting:
./median_stream.go:14: cannot use &hi (type *IntMaxHeap) as type heap.Interface in function argument:
*IntMaxHeap does not implement heap.Interface (missing Len method)
./median_stream.go:15: cannot use &hi (type *IntMaxHeap) as type heap.Interface in function argument:
*IntMaxHeap does not implement heap.Interface (missing Len method)
./median_stream.go:16: cannot use &hi (type *IntMaxHeap) as type heap.Interface in function argument:
*IntMaxHeap does not implement heap.Interface (missing Len method)
./median_stream.go:17: cannot use &hi (type *IntMaxHeap) as type heap.Interface in function argument:
*IntMaxHeap does not implement heap.Interface (missing Len method)
How can I make two structs ("classes") which differ with just one method implementation? The working version should print 3 biggest numbers from the heap.
答案1
得分: 2
在Go语言中,当你声明一个新类型时,它不会继承底层类型的方法。如果你确实想要继承方法,可以考虑使用组合:
type IntMaxHeap struct {
IntHeap
}
func (h IntMaxHeap) Less(i, j int) bool { return h.IntHeap[i] > h.IntHeap[j] }
如果你有一个已经初始化的IntHeap
(或者任何[]int
切片),你可以使用IntMaxHeap{slice}
来构造这个类型,而不需要重新实现其他方法。
这种模式在使用sort
包时可以非常有用,可以声明多个排序方式,而无需重复编写方法。
英文:
When you declare a new type in Go, it doesn't inherit the methods of the underlying type. If you do want to inherit methods, consider using composition:
type IntMaxHeap struct {
IntHeap
}
func (h IntMaxHeap) Less(i, j int) bool { return h.IntHeap[i] > h.IntHeap[j] }
If you have a primed IntHeap
(or any []int
slice, for that matter), you can construct this type with IntMaxHeap{slice}
without needing to reimplement the other methods.
This pattern can be quite useful to declare multiple orderings for use with the sort
package, without duplicating methods.
答案2
得分: 1
简短回答:你不能这样做。Go语言没有方法继承。你能做的最简单的方式是使用匿名字段(参见结构体类型的规范),但你会失去切片的机制。
你需要为每种类型重新实现接口。但你可以聪明地做,通过使用一个未导出的函数来完成工作,并只返回该函数的结果。这样可以节省一些输入,并确保你的方法具有相同的内部工作方式。
示例:
type A []int
func (a A) Len() int {
return getLen(a)
}
type B []int
func (b B) Len() int {
return getLen(a)
}
func getLen(slice []int) int {
return len(slice)
}
显然,我的示例很愚蠢,因为我只是包装了内置的len
函数,但对于更长的函数(比如不止一行的函数),这是非常有用的。
英文:
Short answer: you can't. Go has no method inheritance. The shortest you could get is by using anonymous fields (see the spec about struct types), but you will lose the slice mechanics.
You will have to re-implement the interface for each type. But you can do it smartly, by using an unexported function to do the job, and just return the result of this function. That could save you a few typing and ensure your methods have the same inner workings.
Example:
type A []int
func (a A) Len() int {
return getLen(a)
}
type B []int
func (b B) Len() int {
return getLen(a)
}
func getLen(slice []int) int {
return len(slice)
}
Obviously my example is dumb, because I'm just wrapping the len
built-in, but for longer functions (say, other that oneliners), it is quite useful.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论