这里只是一个与语言设计相关的简单问题。 在像Swift这样的语言中,为了使结构体/类符合协议/接口,需要明确地声明它。
struct Dog: Animal {
// implementation of Animal protocols here
}
但是为什么在Go语言中,没有明确的方式来显示一个结构体符合哪些接口呢?
这难道不会使事情变得不清晰吗?还是说背后还有其他原因?
这里只是一个与语言设计相关的简单问题。 在像Swift这样的语言中,为了使结构体/类符合协议/接口,需要明确地声明它。
struct Dog: Animal {
// implementation of Animal protocols here
}
但是为什么在Go语言中,没有明确的方式来显示一个结构体符合哪些接口呢?
这难道不会使事情变得不清晰吗?还是说背后还有其他原因?
这些引用来自于2012年的一篇文章,以及这个线程,您可以在其中阅读Rob Pike的评论:
“在面向对象的语言中,我一直感到不舒服的是我们可以将Circle、Square等子类定义为Shape(比方说),但那是我们能做出的唯一设计决策。
如果我们想要将这些东西沿其他轴线对齐(说白了),比如拓扑层级或植物属分类,如果你是一个园艺工作者,你可能会迷失方向或陷入多重继承的泥潭。”
扩展VonC的答案。
从问题中可以看出:
但为什么在Go中,没有明确的方式显示一个结构体符合哪些接口呢?
实际上有一些方法。请参见 Go FAQ: 如何确保我的类型满足一个接口?
假设我们有以下接口:
type Sayer interface {
Say() string
}
我们想要创建一个实现它的新类型:
type MySayer struct{}
func (ms MySayer) Say() string {
return "Foo"
}
MySayer
实现了 Sayer
。为确保它实现了该接口,您可以添加以下行:var _ Sayer = MySayer{}
Say()
方法命名为Sai()
,那么它将成为编译时错误。MySayer
实现了Sayer
。为此,您可以添加一个“虚拟”的方法,其名称本身就可以记录这个属性:type Sayer interface {
Say() string
ImplementsSayer()
}
Sayer
,它们必须声明一个名为 ImplementsSayer()
的方法,这个方法一眼就能告诉你它实现了 Sayer
。func (MySayer) ImplementsSayer() {}
Sayer
。但正如常见问题解答所说:
大多数代码都不使用这种约束条件,因为它们限制了接口思想的实用性。然而,有时候它们是必要的,以解决类似接口之间的歧义。