[英]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提到的原因。
回应你最近的评论: “我只是想确保框架的用户得到一些关于如何最好地使用接口的提示。”
如果我的目标是向我的用户建议最佳实践,我会在某个地方记录下来。 是的,有这样一个神话,没有人阅读过文档,但无论如何,如果您允许B
与A
组合,那么您设计的语义正是“B 可以具有 A 的行为”。 因此,警告您的用户这一点是没有实际意义的。 这就像你给你的客户一把锤子说“记住,这是一个 B 型锤子”。 好吧,它仍然是一把锤子。 如果您想赋予您的客户敲钉子的能力,他们从哪里得到锤子,以及任何相关的警告,都是无关紧要的。
至于技术细节:
类型的方法集是编译器需要确定类型是否满足接口的全部内容。 这些方法如何到达那里是无关紧要的。
不幸的是,Go 规格对于这一点并不是非常简单,但可以拼凑出一个解释。
如果
xf
是表示该字段或方法f
的合法选择器,则称为提升结构x
中嵌入字段的字段或方法f
。
合法的选择器:
选择器
f
可以表示类型 T 的字段或方法f
,或者它可以引用T
的嵌套嵌入字段的字段或方法f
那么b.Myfunc
是合法的选择器吗? 是的,因为它引用了嵌入结构的方法。 这种方法称为提升。 然后:
给定一个结构类型
S
和一个定义类型T
,提升的方法包含在结构的方法集中 [...继续描述嵌入T
与*T
的规则]
最后:
类型的方法集决定了该类型实现的接口
这就是您可以从规格中获得的全部信息。 没有提及为什么或如何将方法包含在方法集中以满足接口的目的。
现在唯一的附加信息是,当B
确实在其方法中设置了MyFunc
时直接和通过嵌入A
,如果您调用b.MyFunc
, B
的实现将由于深度规则而运行,这是一种正式的方式,实质上, 定义类似于 OOP 中覆盖的行为:选择器xf
表示f
处于最浅深度,当f
来自嵌入类型A
时,其深度是其在A
+1 中的深度,而直接声明的方法具有深度 0 .
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.