有没有办法约束(通用)类型参数?

有没有办法约束(通用)类型参数?

php小编柚子探讨了一个常见问题:有没有办法约束(通用)类型参数?在PHP中,我们经常需要对函数或方法的参数进行类型约束,以确保传入的参数满足特定的类型要求。然而,对于通用类型参数,如数组或对象,目前还没有直接的约束方式。但是,我们可以通过编写更加严格的类型检查逻辑来实现对通用类型参数的约束,以确保参数的正确性和一致性。在本文中,我们将探讨几种实现通用类型参数约束的方法,以及它们的优缺点。

问题内容

我刚刚开始学习泛型。因此,我尝试为在某些 protobuf 消息上运行的自定义数据库通用一个驱动程序。

我想找到一种方法来进一步约束我的泛型类型,但作为指针,即确保(告诉编译器)约束 e 实现了另一种方法。

首先,我限制了数据库可以处理的实体。

type entity interface {   pb.msga | pb.msgb | pb.msgc}

登录后复制

然后,编写了一个描述数据库功能的通用接口,以便处理各自的原始消息的不同服务可以使用它:

type db[e entity] interface {   get(...) (e, error)   list(...) ([]e, error)   ...}

登录后复制

到目前为止一切顺利。但是,我还希望在与数据库通信时对这些实体进行(反)序列化,以便通过网络发送、克隆和合并。像这样的事情:

func encode[e entity](v *e) ([]byte, error) {   return proto.marshal(v)}

登录后复制

但是,上面的代码给出了以下错误:

cannot use val (variable of type *e) as type protoreflect.protomessage in argument to proto.marshal: *e does not implement protoreflect.protomessage (type *e is pointer to type parameter, not type parameter)

登录后复制

问题是 proto.marshal 需要实体(*e)来实现 proto.message 接口,即 protoreflect() 方法,我所有的实体类型都实现了该方法,但它不受约束,编译器无法推断。

我还尝试将实体定义为:

type Entity interface {   *pb.MsgA | *pb.MsgB | *pb.MsgC   proto.Message}

登录后复制

但是,除了我需要执行一些额外的 protreflect 操作来实例化实体指针引用的 proto.messages 之外,这感觉不太对。

解决方法

你可以这样做:

func encode[m interface { *e; proto.message }, e entity](v m) ([]byte, error) {    return proto.marshal(v)}

登录后复制

如果您想要比上面更简洁的语法,您可以取消消息约束:

type Message[E Entity] interface {    *E    proto.Message}func Encode[M Message[E], E Entity](v M) ([]byte, error) {    return proto.Marshal(v)}

登录后复制

https://www.php.cn/link/20ba66f905957b34253d9d7abde919f3

以上就是有没有办法约束(通用)类型参数?的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2357270.html

(0)
上一篇 2025年3月1日 16:18:52
下一篇 2025年3月1日 16:19:08

AD推荐 黄金广告位招租... 更多推荐

相关推荐

发表回复

登录后才能评论