【问题标题】:Golang inferred interfacesGolang 推断接口
【发布时间】:2017-05-17 03:55:42
【问题描述】:

这里只是一个简单的语言设计相关问题。 在像 Swift 这样的语言中,为了使结构/类符合协议/接口,需要显式声明它

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

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

这不是说不清楚还是有其他原因?

【问题讨论】:

标签: go interface language-design implements


【解决方案1】:

这允许演变为甚至为遗留类型提供接口(从未明确声明尊重所述接口)

如果这些类型已经提供了正确的方法(即与您的接口指定的 API 相同的 API),它们将满足该接口。

这允许在那些遗留类型(它们不知道你的接口存在)和你的程序之间保持低耦合,它接受该接口的实例。

见“What are some examples of Go interfaces?

Go 的接口不是 Java 或 C# 接口的变体,它们更多。
它们是大规模编程和适应性进化设计的关键。

“事实上,我不必花时间预先设计某种类型层次结构,然后在完成之前重新排列它两到三遍。
正确地做这件事甚至不是一件容易的事 -
事实上,我不必担心它,可以继续使用实际的算法。”

这些引用来自2012 article,也来自this thread,您可以在其中阅读Rob Pike's comment

“在 OO 语言中,我们可以将 Circle、Square 等作为 Shape 的子类(比如说)一直困扰着我,但这是我们必须做出的一个设计决策。
如果我们想沿着其他轴(可以这么说)对齐这些东西,比如拓扑属或植物属,如果你是一名园艺师,该怎么办?您可能会迷失方向,或者将自己挖进多重继承的坑中。”

【讨论】:

    【解决方案2】:

    扩展 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 本身 记录了此属性:

    type Sayer interface {
        Say() string
        ImplementsSayer()
    }
    

    现在任何类型要实现Sayer,都必须声明一个名为ImplementsSayer()的方法,一眼就能看出它实现了Sayer

    func (MySayer) ImplementsSayer() {}
    

    您甚至不需要命名接收器,因为它没有被使用。该行用简单的英语写成:“MySayer implements Sayer”

    由于这个方法被导出(以大写字母开头),它也出现在文档中,当面告诉你它实现了Sayer。但正如常见问题解答所说:

    大多数代码都没有使用这些约束,因为它们限制了界面思想的实用性。但有时,它们对于解决相似接口之间的歧义是必要的。

    【讨论】:

      猜你喜欢
      • 2021-01-11
      • 2022-11-24
      • 2014-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多