这里只是一个简单的语言设计相关问题。 在像Swift这样的语言中,为了使struct / class符合协议/接口,需要明确地将其声明为
struct Dog: Animal {
// implementation of Animal protocols here
}
但为什么在Go中,没有明确的方法来显示结构符合的接口?
这不仅仅是让事情不清楚,还是还有其他原因?
答案 0 :(得分:7)
这允许进化甚至为遗留类型(从未明确声明尊重所述接口)提供接口
如果这些类型已经提供了正确的方法(即与您的接口指定的API相同的API),它们将满足该接口。
这允许在那些遗留类型(不知道你的接口存在)和接受该接口实例的程序之间保持低耦合。
请参阅“What are some examples of Go interfaces?”
Go的接口不是Java或C#接口的变种,它们更多 它们是大规模编程和适应性进化设计的关键。
“事实上,我不必花时间设计某种类型的层次结构,然后在我完成之前将其重新排列两到三次。
它甚至不是很容易做到的事实 -
这是事实,我只是不必担心它,并可以继续使用实际的算法。“
这些引用来自此2012 article,也来自this thread,您可以在其中阅读Rob Pike's comment:
“在OO语言中我总是困扰我们,我们可以制作Shape的圆形,方形等子类(比如说),但这是我们要做出的一个设计决定。
如果我们想要将这些东西与其他轴(可以这么说)对齐,如拓扑属或植物属,如果你是园林师怎么办?你可能会迷失方向,或者陷入多重继承的洞中。“
答案 1 :(得分:3)
扩展VonC的答案。
从问题:
但为什么在Go中,没有明确的方法来显示结构符合的接口?
实际上有一些方法。见Go FAQ: How can I guarantee my type satisfies an interface?
我们说我们有以下界面:
type Sayer interface {
Say() string
}
我们想创建一个实现它的新类型:
type MySayer struct{}
func (ms MySayer) Say() string {
return "Foo"
}
在这种情况下MySayer
实施Sayer
。要确保它,您可以添加以下行:
var _ Sayer = MySayer{}
你应该输错一些东西吗,例如将Say()
方法命名为Sai()
,这将是编译时错误。
尽管如此,这只是一个编译时间"检查",它并没有记录MySayer
实现Sayer
。为此,您可以添加一个"虚拟" name name 的方法记录了这个属性:
type Sayer interface {
Say() string
ImplementsSayer()
}
现在,对于任何要实现Sayer
的类型,他们必须声明一个名为ImplementsSayer()
的方法,只需一瞥即可判断它是否实现了Sayer
:
func (MySayer) ImplementsSayer() {}
您甚至不需要为未使用的接收器命名。该行用简单的英语读取:" MySayer实现了Sayer" 。
由于此方法已导出(以大写字母开头),因此它也会显示在文档中,告诉您它实现了Sayer
。但正如FAQ所说:
大多数代码都没有使用这些约束,因为它们限制了界面理念的效用。但有时,他们需要解决类似界面之间的歧义。