类型约束(E)未被具体结构中的嵌入(E)满足。

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

Type constraint (E) not met by embedding (E) in concrete struct

问题

我正在尝试实现一种变体的类型参数的指针方法示例设计模式,以便在一些统一的存储库接口上进行抽象。

我原本以为如果Person结构体组合了*Entity,它会继承Entity的方法集,但是我得到了一个编译时错误,如下所示。请问有人可以解释为什么类型约束没有满足以及如何修复这段代码吗?

对于标题的糟糕选择我表示歉意;如果有人能提出一个改进的摘要,那将非常棒(我对Go语言还很新)。

谢谢 类型约束(E)未被具体结构中的嵌入(E)满足。

package main

// 领域

type PEntity[E any] interface {
	*E
	SetID(id string)
}

type Entity struct {
	ID string
}

func (e Entity) SetID(id string) {
	e.ID = id
}

type Repository[E Entity, PE PEntity[E]] interface {
	Get(id string) *E
}

// 数据

type Person struct {
	*Entity
}

type PersonRepository interface {
	Repository[Person, *Person] // -> Person does not implement Entity
	AddPet(name string)
	// ...
}
英文:

I'm trying to implement a variation of the pointer-method example for type-parameters design pattern, in order to abstract over some unified repository interface.

I was under the impression that the Person struct would inherit the method-set of Entity if it composes *Entity, but I get a compile-time error as below. Could someone please explain why the type-constraint is not met and how to fix this code?

Apologies for the awful title; if someone could suggest an improved summary that would be fantastic (I'm quite new to Go).

Thanks 类型约束(E)未被具体结构中的嵌入(E)满足。

package main

// domain

type PEntity[E any] interface {
	*E
	SetID(id string)
}

type Entity struct {
	ID string
}

func (e Entity) SetID(id string) {
	e.ID = id
}

type Repository[E Entity, PE PEntity[E]] interface {
	Get(id string) *E
}

// data

type Person struct {
	*Entity
}

type PersonRepository interface {
	Repository[Person, *Person] // -> Person does not implement Entity
	AddPet(name string)
	// ...
}

答案1

得分: 2

约束E Entity是对E interface{ Entity }的语法糖,它实际上意味着E类型集合只包含一个类型项Entity,该类型项是一个结构体。

当你有确切的约束时,你只能用该类型来满足它们,所以它与根本没有类型参数并声明常规函数参数没有太大区别。以下是一个示例,帮助你理解:

func Foo[T int](v T) {}

实际上与以下代码几乎相同:

func Foo(v int) {}

因此,你可以通过结构体Entity来满足约束E Entity

显然,Person不是Entity。字段嵌入只影响嵌入类型的方法集,对类型标识没有影响。

如果你将约束更改为仅包含方法的基本接口,或者直接更改Entityplayground),那么它将只考虑方法集,并成功编译:

type Repository[E interface{ SetID(id string) }, PE PEntity[E]] interface {
	Get(id string) *E
}

关于基本接口和非基本接口的更多信息:https://stackoverflow.com/questions/71073365/interface-contains-type-constraints-cannot-use-interface-in-conversion/71076143#71076143

英文:

The constraint E Entity — syntactic sugar for E interface{ Entity } — effectively means that the type set of E includes exactly one type term Entity, which is a struct.

When you have exact constraints, you can only satisfy them with that very type, so it doesn't make much difference from not having the type parameter at all and declaring regular function arguments. As an example to help you understand:

func Foo[T int](v T) {}

is practically the same as:

func Foo(v int) {}

Therefore you can satisfy the constraint E Entity exclusively with the struct Entity.

Clearly Person is not Entity. Field embedding only affects the method set of the embedding type, which has no bearings on type identity.

If you change the constraint to a method-only (basic) interface — Or or change Entity directly (playground) —, then it will take only the method set into account and successfully compile:

type Repository[E interface{ SetID(id string) }, PE PEntity[E]] interface {
	Get(id string) *E
}

More about basic vs. non-basic interfaces: https://stackoverflow.com/questions/71073365/interface-contains-type-constraints-cannot-use-interface-in-conversion/71076143#71076143

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

发表评论

匿名网友

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

确定