英文:
Type constraint (E) not met by embedding (E) in concrete struct
问题
我正在尝试实现一种变体的类型参数的指针方法示例设计模式,以便在一些统一的存储库接口上进行抽象。
我原本以为如果Person
结构体组合了*Entity
,它会继承Entity
的方法集,但是我得到了一个编译时错误,如下所示。请问有人可以解释为什么类型约束没有满足以及如何修复这段代码吗?
对于标题的糟糕选择我表示歉意;如果有人能提出一个改进的摘要,那将非常棒(我对Go语言还很新)。
谢谢
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
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
。字段嵌入只影响嵌入类型的方法集,对类型标识没有影响。
如果你将约束更改为仅包含方法的基本接口,或者直接更改Entity
(playground),那么它将只考虑方法集,并成功编译:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论