Golang推断出接口

时间:2017-01-03 05:35:27

标签: go interface language-design implements

这里只是一个简单的语言设计相关问题。 在像Swift这样的语言中,为了使struct / class符合协议/接口,需要明确地将其声明为

struct Dog: Animal {
    // implementation of Animal protocols here
}

但为什么在Go中,没有明确的方法来显示结构符合的接口?

这不仅仅是让事情不清楚,还是还有其他原因?

2 个答案:

答案 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所说:

  

大多数代码都没有使用这些约束,因为它们限制了界面理念的效用。但有时,他们需要解决类似界面之间的歧义。