接口实现接口[关闭]

问题描述 投票:-3回答:2

../src/io/io.go,下面的界面有Write方法

type Writer interface {
    Write(p []byte) (n int, err error)
}

../src/net/http/server.go,接口ResponseWriter下面实现了Write接口的Writer方法

type ResponseWriter interface {

    Header() Header

    Write([]byte) (int, error)

    WriteHeader(statusCode int)
}

从编码风格方面来看,Writer界面是否嵌入ResponseWriter界面首选实施呢?

go
2个回答
3
投票

我觉得你在接触embedding

所以在上面的例子中,可以像这样重写接口定义:

type ResponseWriter interface {

    Header() Header

    io.Writer // embedded interface type

    WriteHeader(statusCode int)
}

但这是与io包的预先安排。

http/server.go接口定义能够在不知道io包的情况下存在。

通过http/server.go的界面需要一个功能Writeio.Writer具有相同的签名,这允许许多其他好处,而无需建立与(外部)io包的正式链接。


2
投票

请记住,界面本身根本不执行任何操作。它简单地说,“如果您的软件包使用这些签名实现所有这些功能,那么它可以在需要X接口的地方使用”。

可以把它想象成一种契约类型:“如果我说在这里可以使用FooInterface,那么做任何我所说的FooInterface所做的事情都是可以接受的。”

根据定义,Writer需要以某种方式实现Write。从界面的角度来看,该特定方法的作用并不重要,只有它存在,并且接受byte数组,返回interror。它的作用取决于包的实现。

也许它编程一架无人机来编写字节,也许它会破坏时代广场的广告牌并在那里打印消息。重要的是,至少,您可以调用Write并获得预期的返回值。副作用不是由接口定义的,而是由包中的实现定义的。

具有正确签名的Write函数存在的事实使得包符合Writer接口。它可能有十几种其他方法;只有Write符合要求才有意义。

ResponseWriterWriter只是因为ResponseWriter说“我碰巧要求ResponseWriters实现与Writer相同的接口 - 我们都实现Write([]byte) (int, error);要成为ResponseWriter,它也必须实现HeaderWriteHeader。”如果Skywriting包也实现了这两个函数,那么它将是一个ResponseWriter

type ResponseWriter interface没有定义HeaderWriteHeader做什么,只是他们必须存在并拥有正确的签名。与Writer的关系只是我们已经同意概念上ResponseWriter是一个专门的Writer。完全可以定义一个不包含OddResponseWriterWrite接口(虽然它会令人困惑)。

更专业的名称意味着具有更专业化名称的接口是具有更简单名称的接口的超集,但是Go本身没有强制执行此接口。正如@colminator所说,我们可以通过嵌入更简单的类型来强制执行此操作;这使得编译器可以强制专用接口也满足不太专业化的接口契约,并确保如果嵌入式接口的需求发生变化但嵌入器没有改变以满足它,代码将无法编译。

这种接口实现为我们提供了很大的灵活性,可以将一个包替换为另一个包而无需重写。如果一个函数说“请传递给我一个Writer界面,这样我就可以写出我的结果”,如果你用一个不同的名字交换一个新的包,那么不需要触摸该代码,只要你输入的内容有一个匹配的Writer

© www.soinside.com 2019 - 2024. All rights reserved.