我正在研究Go中一个简单的链表实现,以进行学习。元素的定义如下:
type Element struct {
next, prev *Element
Value interface{}
}
如您所见,Value可以是满足空接口的任何值。现在,作为一项新功能,我要进行创建,以便在将新元素插入列表时,它以排序方式插入-每个元素将是<=下一个元素。
为了做到这一点,我编写了以下方法:
func (l *LinkedList) Add(val interface{}) *Element {
this := &l.Root
e := Element{Value: val}
for {
if this.next.Value != nil && this.next.Value < val { // <-comparison here
this = this.next
} else {
return l.insert(&e, this)
}
}
}
编译器抱怨operator < not defined on interface
这是公平的。因此,我知道在Element
typedef中,我应该将Value限制为可以使用<
运算符进行比较的类型。我在研究Go不支持运算符重载的问题时了解了这一点-
我不是在尝试这样做。相反,我只是试图确保Element.Value是可以使用<
运算符进行比较的类型。我该怎么做呢?
在我看来,简单地定义一个基于内置的新类型可能并不难,可以通过某些功能进行比较。所以我写了这个烂摊子(以及尝试做同一件事的其他方法):
type Comparable interface {
LessThan(j interface{}) bool // tried (j Comparable), (j MyInt), etc
EqualTo(j interface{}) bool // tried (j Comparable), (j MyInt), etc
}
type MyInt int
func (i MyInt) LessThan(j MyInt) bool {
return i < j
}
func (i MyInt) EqualTo(j MyInt) bool {
return i == j
}
type Element struct {
next, prev *Element
Value Comparable
}
我真正想要的是定义一个接口,如果为一种类型实现,则可以提供函数LessThan
,EqualTo
并且可以在该类型的两个实例上运行并提供bool-
LessThan(i, j WhatEvers) bool
可以代替<
。我意识到在下面它是作为实例方法实现的-
我尝试了两种方法,但没有成功。有了以上内容,我将this.next.Value.LessThan(val)
在Add函数中使用类似的方法:我得到:
linkedlist.MyInt does not implement linkedlist.Comparable (wrong type for EqualTo method)
have EqualTo(linkedlist.MyInt) bool
want EqualTo(interface {}) bool
要么
linkedlist.MyInt does not implement linkedlist.Comparable (wrong type for EqualTo method)
have EqualTo(linkedlist.MyInt) bool
want EqualTo(linkedlist.Comparable) bool
是否可以使用接口来要求必须存在对自定义类型的两个实例进行操作的某个函数,或者仅用于方法?
编辑:
考虑此用户类型:
type userType struct {
frequency int
value rune
}
并假设您想将此类型添加到“链接列表”:
并且应首先按频率对其进行排序,然后,如果频率相同,请查看char值。因此该Compare
函数将是:
func (a userType) Compare(b userType) int {
if a.frequency > b.frequency {
return 1
}
if a.frequency < b.frequency {
return -1
}
if a.value > b.value {
return 1
}
if a.value < b.value {
return -1
}
return 0
}
满足以下接口:
type Comparer interface {
Compare(b userType) int
}
现在将这些{1,'d'} {2,'b'} {3,'c'} {4,'a'} {4,'b'} {4,'c'}
类型添加到LinkeList:
示例代码:
package main
import (
"container/list"
"fmt"
)
type Comparer interface {
Compare(b userType) int
}
type userType struct {
frequency int
value rune
}
// it should sort by frequency first, then if the frequencies are the same, look at the char value.
func (a userType) Compare(b userType) int {
if a.frequency > b.frequency {
return 1
}
if a.frequency < b.frequency {
return -1
}
if a.value > b.value {
return 1
}
if a.value < b.value {
return -1
}
return 0
}
func Insert(val userType, l *list.List) {
e := l.Front()
if e == nil {
l.PushFront(val)
return
}
for ; e != nil; e = e.Next() {
var ut userType = e.Value.(userType)
if val.Compare(ut) < 0 {
l.InsertBefore(val, e)
return
}
}
l.PushBack(val)
}
func main() {
l := list.New()
Insert(userType{4, 'c'}, l)
Insert(userType{4, 'a'}, l)
Insert(userType{4, 'b'}, l)
Insert(userType{2, 'b'}, l)
Insert(userType{3, 'c'}, l)
Insert(userType{1, 'd'}, l)
for e := l.Front(); e != nil; e = e.Next() {
ut := e.Value.(userType)
fmt.Printf("{%d,%q} ", ut.frequency, ut.value)
}
fmt.Println()
var t interface{} = userType{4, 'c'}
i, ok := t.(Comparer)
fmt.Println(i, ok)
}
并输出:
{1,'d'} {2,'b'} {3,'c'} {4,'a'} {4,'b'} {4,'c'}
{4 99} true
因此,如果您准备使用已知类型(例如int
),请参见以下示例:
package main
import (
"container/list"
"fmt"
)
func Insert(val int, l *list.List) {
e := l.Front()
if e == nil {
l.PushFront(val)
return
}
for ; e != nil; e = e.Next() {
v := e.Value.(int)
if val < v {
l.InsertBefore(val, e)
return
}
}
l.PushBack(val)
}
func main() {
l := list.New()
Insert(4, l)
Insert(2, l)
Insert(3, l)
Insert(1, l)
for e := l.Front(); e != nil; e = e.Next() {
fmt.Print(e.Value, " ") // 1 2 3 4
}
fmt.Println()
}
旧:
Go中没有这样的界面。您可以编写此Less
函数来比较您的类型:
func Less(a, b interface{}) bool {
switch a.(type) {
case int:
if ai, ok := a.(int); ok {
if bi, ok := b.(int); ok {
return ai < bi
}
}
case string:
if ai, ok := a.(string); ok {
if bi, ok := b.(string); ok {
return ai < bi
}
}
// ...
default:
panic("Unknown")
}
return false
}
测试示例代码:
package main
import (
"container/list"
"fmt"
)
func Less(a, b interface{}) bool {
switch a.(type) {
case int:
if ai, ok := a.(int); ok {
if bi, ok := b.(int); ok {
return ai < bi
}
}
case string:
if ai, ok := a.(string); ok {
if bi, ok := b.(string); ok {
return ai < bi
}
}
default:
panic("Unknown")
}
return false
}
func Insert(val interface{}, l *list.List) *list.Element {
e := l.Front()
if e == nil {
return l.PushFront(val)
}
for ; e != nil; e = e.Next() {
if Less(val, e.Value) {
return l.InsertBefore(val, e)
}
}
return l.PushBack(val)
}
func main() {
l := list.New()
Insert(4, l)
Insert(2, l)
Insert(3, l)
Insert(1, l)
for e := l.Front(); e != nil; e = e.Next() {
fmt.Print(e.Value, " ")
}
fmt.Println()
Insert("C", l)
Insert("A", l)
Insert("AB", l)
Insert("C", l)
Insert("C2", l)
Insert("C1", l)
for e := l.Front(); e != nil; e = e.Next() {
fmt.Print(e.Value, " ")
}
fmt.Println()
}
输出:
1 2 3 4
1 2 3 4 A AB C C C1 C2
当我在浏览上面的接口时,在阅读了许多相同主题的站点后,我对这些接口的语法不是很清楚。 请考虑以下代码段: 如果每个查询都是可理解的。
假设您有ClassA、ClassB、ClassC和InterfaceA。 ClassA和ClassB实现interfaceA,而classC包含一个列表
实际上,我想对对象数组列表进行排序。我正在为此目的使用可比接口。它是完全有效的,但问题是,当我排序的时候,是给这两个问题。 > 所有名字中有第一个字母大写的都在上面,所有名字中有第一个字母小写的都在下面。 所有排序的大写字母单词都在一起,然后所有的小写字母单词都在一起。
接口在Java11中获得了一个新的静态方法:。 此方法返回int: 如果两个字符序列相等,则值为0;如果第一个字符序列在词典编纂上小于第二个字符序列,则为负整数;或者,如果第一个字符序列在词典上大于第二个字符序列,则为正整数。 这听起来就像是可比的。然而,Java团队显然选择了不让CharSequence可比。为什么不呢?我无法理解这种逻辑。 什么是关于,这将不是一个适当的适合?
重写Compariable接口的compareTo()方法的最佳方法是什么?此外,当我们可以编写自己的compareTo()方法而无需实现时,为什么还要实现可比较的接口呢。以以下座椅类别为例: 尽管我们没有实现可比接口,但上述工作仍然有效,那么我们为什么要实现它呢?
问题内容: 我不确定如何在我的抽象类中实现类似的接口。我有以下示例代码可用来尝试解决这个问题: 我有一个测试类,该类将创建Animal类型的对象,但是我希望在该类中具有一个可比的接口,以使发现的年纪高于低位。我不知道如何去解决这个问题。 问题答案: 您只需要定义即p。然后,您必须以自己喜欢的方式实现该方法。 使用的实现,具有较高级别的动物将获得更高的顺序。我希望你的想法和这个例子。