如何通过泛型中的嵌入来满足实现的约束条件?

huangapple go评论117阅读模式
英文:

How to satisfy a constraint implemented through embedding in generics?

问题

我有一个接口:

  1. type FooInterface interface {
  2. HasName() bool
  3. }

它有一个基本实现,我打算在其他实现FooInterface的地方使用:

  1. type FooBoilerplate struct {
  2. hasName bool
  3. }
  4. func (f *FooBoilerplate) HasName() bool {
  5. return f.hasName
  6. }

像这样:

  1. type Foo1 struct {
  2. fooId int
  3. FooBoilerplate
  4. }
  5. func (f *Foo1) GetId() int {
  6. return f.fooId
  7. }

我想使用泛型创建一个包含FooInterface的容器类:

  1. type FooContainer[T FooInterface] struct {
  2. list []T
  3. }
  4. func (fc *FooContainer[T]) AddItem() {
  5. var t T
  6. fc.list = append(fc.list, t)
  7. }

然而,当我尝试实例化容器时,我遇到了编译错误:

  1. func RunThis() {
  2. foo1 := Foo1{FooBoilerplate: FooBoilerplate{hasName: false}}
  3. // 正常工作
  4. TakesFooInterface(&foo1)
  5. // 无法编译
  6. fc := FooContainer[Foo1]{}
  7. fc.AddItem()
  8. }

不确定为什么当将Foo1传递给函数时,它被视为实现了FooInterface,但当传递给容器结构时却不是。我也无法将对象传递给容器实例化。

英文:

I have an interface

  1. type FooInterface interface {
  2. HasName() bool
  3. }

It has a base implementation that I intend to use in other implementation of FooInterface

  1. type FooBoilerplate struct {
  2. hasName bool
  3. }
  4. func (f *FooBoilerplate) HasName() bool {
  5. return f.hasName
  6. }

Like so

  1. type Foo1 struct {
  2. fooId int
  3. FooBoilerplate
  4. }
  5. func (f *Foo1) GetId() int {
  6. return f.fooId
  7. }

I want to create a container class for FooInterface using generics

  1. type FooContainer[T FooInterface] struct {
  2. list []T
  3. }
  4. func (fc *FooContainer[T]) AddItem() {
  5. var t T
  6. fc.list = append(fc.list, t)
  7. }

However I get compilation errors when I try to instantiate the container

  1. func RunThis() {
  2. foo1 := Foo1{FooBoilerplate: FooBoilerplate{hasName: false}}
  3. // works fine
  4. TakesFooInterface(&foo1)
  5. // doesnt compile
  6. fc := FooContainer[Foo1]{}
  7. fc.AddItem()
  8. }

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来实例化泛型类型:

  1. 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:

  1. fc := FooContainer[*Foo1]{}

答案2

得分: 0

我假设你的TakesFooInterface是这样的:

  1. func TakesFooInterface(foo1 FooInterface) {
  2. ...
  3. }

然后调用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:

  1. func TakesFooInterface(foo1 FooInterface) {
  2. ...
  3. }

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

huangapple
  • 本文由 发表于 2022年6月25日 15:23:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/72752010.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定