泛型:实现嵌套接口

3

我正在尝试使用泛型实现接口Interface。它有一个方法,该方法接受另一个接口作为参数:

type SubInterface interface {
    SendResponse(string)
}

type Interface interface {
    Subscribe(SubInterface)
}

我已经想出了以下这些接口的通用版本:
type GenericSubInterface[T any] interface {
    SendResponse(T)
}

type GenericInterface[Res any] interface {
    Subscribe(GenericSubInterface[Res])
}

我希望 `GenericInterface[string]` 可以赋值给 `Interface`,但它似乎并不能。
var a Interface
var b GenericInterface[string]

//  cannot use b (variable of type GenericInterface[string]) as Interface value in assignment: GenericInterface[string] does not implement Interface (wrong type for method Subscribe)
//      have Subscribe(GenericSubInterface[string])
//      want Subscribe(SubInterface)
a = b

创建一个通用的Interface实现也不起作用:

type GenericImplementation[Res any] struct {
}

func (i *GenericImplementation[Res])Subscribe(ss GenericSubInterface[Res]) {
    var msg Res
    ss.SendResponse(msg)
}

//  cannot use &GenericImplementation[string]{} (value of type *GenericImplementation[string]) as Interface value in variable declaration: *GenericImplementation[string] does not implement Interface (wrong type for method Subscribe)
//      have Subscribe(GenericSubInterface[string])
//      want Subscribe(SubInterface)
var c Interface = &GenericImplementation[string]{}

对我来说奇怪的是,子接口可以相互赋值:

var d SubInterface
var e GenericSubInterface[string]

// works fine
d = e

当接口以某种方式嵌套时,问题似乎只会出现。有没有办法绕过这个问题,我可以使用泛型来实现除了字符串之外的其他类型的Interface

完整的示例代码

2个回答

3
首先,阅读Go接口:即使已实现但未实现接口。在@colm.anseo的答案中,第一句话就已经概括了问题:

签名不同,参数类型不同

然后阅读如何实现通用接口?。类型为SubInterface 的值可以分配给GenericSubInterface[string]特定实例,因为方法最终变得相同 — SendResponse(string)Interface无法分配给GenericInterface[string],因为方法最终不相同。错误消息如下:
have Subscribe(GenericSubInterface[string])
want Subscribe(SubInterface)

你可以使用接口的通用版本,但方法必须精确实现。因此,你需要将函数 AcceptInterface 也设为通用型:
func AcceptInterface[T any](a GenericInterface[T]) {
}

func main() {
    var b GenericInterface[string]
    AcceptInterface(b)
}

我理解错了,本来以为这是泛型的问题,其实不是。 如果“func AcceptInterface(a Interface)”不在我的控制范围内,那么没有办法传递一个通用实现吗? - Fiduro
2
只有在实例化后,实现者具有相同的方法签名,才能传递通用实现。 - blackgreen

1

我已经找到了一种解决方案,使用泛型来满足我的需求,可以使得Interface更加通用。任何嵌套的接口都必须指定为额外的类型参数。这使得实例化有点冗长,但允许GenericInterfaceGenericImplementation满足Interface

// Interface

type GenericInterface[Res any, Arg GenericSubInterface[Res]] interface {
    Subscribe(Arg)
}

var a Interface
var b GenericInterface[string, SubInterface]
a = b // works

// Implementation

type GenericImplementation[Res any, Arg GenericSubInterface[Res]] struct {
}

func (i *GenericImplementation[Res, Arg]) Subscribe(ss Arg) {
    var msg Res
    ss.SendResponse(msg)
}

var c Interface = &GenericImplementation[string, SubInterface]{} // works

请注意,GenericInterface[string, SubInterface]是唯一可分配给Interface的实例化。 - blackgreen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接