英文:
How to satisfy a constraint implemented through embedding in generics?
问题
我有一个接口:
type FooInterface interface {
HasName() bool
}
它有一个基本实现,我打算在其他实现FooInterface的地方使用:
type FooBoilerplate struct {
hasName bool
}
func (f *FooBoilerplate) HasName() bool {
return f.hasName
}
像这样:
type Foo1 struct {
fooId int
FooBoilerplate
}
func (f *Foo1) GetId() int {
return f.fooId
}
我想使用泛型创建一个包含FooInterface的容器类:
type FooContainer[T FooInterface] struct {
list []T
}
func (fc *FooContainer[T]) AddItem() {
var t T
fc.list = append(fc.list, t)
}
然而,当我尝试实例化容器时,我遇到了编译错误:
func RunThis() {
foo1 := Foo1{FooBoilerplate: FooBoilerplate{hasName: false}}
// 正常工作
TakesFooInterface(&foo1)
// 无法编译
fc := FooContainer[Foo1]{}
fc.AddItem()
}
不确定为什么当将Foo1传递给函数时,它被视为实现了FooInterface,但当传递给容器结构时却不是。我也无法将对象传递给容器实例化。
英文:
I have an interface
type FooInterface interface {
HasName() bool
}
It has a base implementation that I intend to use in other implementation of FooInterface
type FooBoilerplate struct {
hasName bool
}
func (f *FooBoilerplate) HasName() bool {
return f.hasName
}
Like so
type Foo1 struct {
fooId int
FooBoilerplate
}
func (f *Foo1) GetId() int {
return f.fooId
}
I want to create a container class for FooInterface using generics
type FooContainer[T FooInterface] struct {
list []T
}
func (fc *FooContainer[T]) AddItem() {
var t T
fc.list = append(fc.list, t)
}
However I get compilation errors when I try to instantiate the container
func RunThis() {
foo1 := Foo1{FooBoilerplate: FooBoilerplate{hasName: false}}
// works fine
TakesFooInterface(&foo1)
// doesnt compile
fc := FooContainer[Foo1]{}
fc.AddItem()
}
Not sure why Foo1 is seen to implement FooInterface when passed to a function, but isnt when passed tot he container struct. I cant pass an object to the container instantiation either.
答案1
得分: 2
Foo1
没有实现FooInterface
接口,而*Foo1
实现了该接口。无论接口是作为函数参数的类型还是作为约束条件,这都是正确的。
这就是为什么你将&foo1
(类型为*Foo1
)传递给TakesFooInterface
,而不是foo1
(类型为Foo1
)。
同样,对于类型参数,你应该使用*Foo1
来实例化泛型类型:
fc := FooContainer[*Foo1]{}
英文:
Foo1
doesn't implement FooInterface
. *Foo1
does. This is true irrespective of whether the interface is used as the type of a function argument or as a constraint.
That is why you pass &foo1
(type *Foo1
) to TakesFooInterface
and not foo1
(type Foo1
).
Likewise for the type parameter, you should instantiate the generic type with *Foo1
:
fc := FooContainer[*Foo1]{}
答案2
得分: 0
我假设你的TakesFooInterface是这样的:
func TakesFooInterface(foo1 FooInterface) {
...
}
然后调用TakesFooInterface(foo1)无法编译通过,因为foo1并没有实现FooInterface,而是&foo1。
对于你的泛型情况也是一样,Foo1
类型并没有实现需要在方法HasName
中使用指针访问的FooInterface,但*Foo1
类型有。
我在Go.Dev上复制了你的代码,并进行了一些尝试:https://go.dev/play/p/3I2mtabi-ub
英文:
I assume your TakesFooInterface is like this:
func TakesFooInterface(foo1 FooInterface) {
...
}
Then the call TakesFooInterface(foo1) failed to compile, as foo1 does not implement FooInterface but &foo1.
The same with your generic case, the Foo1
type does not implement FooInterface which requires the pointer access in the method HasName
but *Foo1
type does.
I have copied your code with some of my tryings on Go.Dev: https://go.dev/play/p/3I2mtabi-ub
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论