繁体   English   中英

检查 Go 类型是否阴影/实现一个嵌入式类型的接口的 function

[英]Check if Go type shadows/implements one function of an embedded type's interface

type A interface {
  MyFunc()
}

type A struct {
}

func (a *A) MyFunc() {...}
 
type B struct {
  *A
}
var _ A = &B{}
var _ A = (*B)(nil)

由于嵌入了 A,B 实现了接口 A。到目前为止,一切都很好。

但是我如何(静态或在运行时)检查 B 实现了自己的MyFunc版本?

更新:没有办法在编译时静态检查。

func (b *B) MyFunc() {...}
var _ ??? = &B{}
var _ ??? = (*B)(nil)

tl;博士你不能,因为@JimB提到的原因。


回应你最近的评论: “我只是想确保框架的用户得到一些关于如何最好地使用接口的提示。”

如果我的目标是向我的用户建议最佳实践,我会在某个地方记录下来。 是的,有这样一个神话,没有人阅读过文档,但无论如何,如果您允许BA组合,那么您设计的语义正是“B 可以具有 A 的行为”。 因此,警告您的用户这一点是没有实际意义的。 这就像你给你的客户一把锤子说“记住,这是一个 B 型锤子”。 好吧,它仍然是一把锤子。 如果您想赋予您的客户敲钉子的能力,他们从哪里得到锤子,以及任何相关的警告,都是无关紧要的。


至于技术细节:

类型的方法集是编译器需要确定类型是否满足接口的全部内容。 这些方法如何到达那里是无关紧要的。

不幸的是,Go 规格对于这一点并不是非常简单,但可以拼凑出一个解释。

如果xf是表示该字段或方法f的合法选择器,则称为提升结构x中嵌入字段的字段或方法f

合法的选择器:

选择器f可以表示类型 T 的字段或方法f ,或者它可以引用T的嵌套嵌入字段的字段或方法f

那么b.Myfunc是合法的选择器吗? 是的,因为它引用了嵌入结构的方法。 这种方法称为提升 然后:

给定一个结构类型S和一个定义类型T ,提升的方法包含在结构的方法集中 [...继续描述嵌入T*T的规则]

最后:

类型的方法集决定了该类型实现的接口

这就是您可以从规格中获得的全部信息。 没有提及为什么或如何将方法包含在方法集中以满足接口的目的

现在唯一的附加信息是,当B确实在其方法中设置了MyFunc时直接和通过嵌入A ,如果您调用b.MyFuncB的实现将由于深度规则而运行,这是一种正式的方式,实质上, 定义类似于 OOP 中覆盖的行为:选择器xf表示f处于最浅深度,当f来自嵌入类型A时,其深度是其在A +1 中的深度,而直接声明的方法具有深度 0 .

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM