如何在Go界面中处理重复方法?
package main
import (
"fmt"
)
type Person interface {
Hello()
}
type Joker interface {
Person
Joke()
}
type Jumper interface {
Person
Jump()
}
type Entertainer interface {
Joker
Jumper
}
func main() {
fmt.Println("hello, world")
}
如果我运行此代码,则会发生以下错误。
$ go run foo.go
# command-line-arguments
./foo.go:24: duplicate method Hello
如何处理这样的情况?在这种情况下如何避免重复方法?
这样做的方法是显式提供所需的方法,而不是使用速记语法:
type Entertainer interface {
Hello()
Joke()
Jump()
}
这看起来像是代码重复,但是请注意,重复代码在Go中并不是一件不典型的事情,尤其是当它导致更清晰的代码时。
另请注意:如果你想在其他语言中典型的继承权,它可能看起来像你做这个丢失一些信息,因为你没有记录的事实,Entertainer
继承
,比如说,从Person
。但是Go接口纯粹是结构性的,没有继承。因为一个Entertainer
具有Hello()
方法,所以每个Entertainer
自动为一个Person
,无论您是否Person
在Entertainer
声明内部明确提及。
即使您不对任何接口使用简写语法,所有这些编译都不会出现问题(“声明的且未使用的”错误除外):
var e Entertainer
var ju Jumper
var jo Joker
var p Person
p = e // every Entertainer is also a Person
p = ju // every Jumper is also a Person
p = jo // every Joker is also a Person
ju = e // every Entertainer is also a Jumper
jo = e // every Entertainer is also a Joker
这是一个完整的程序,可以编译并正常运行。鉴于以下声明:
package main
import (
"fmt"
)
type Person interface {
Hello()
}
type Joker interface {
Hello()
Joke()
}
type Jumper interface {
Hello()
Jump()
}
type Entertainer interface {
Hello()
Joke()
Jump()
}
让我们创建一个Clown
类型:
type Clown struct {}
func (c Clown) Hello() {
fmt.Println("Hello everybody")
}
func (c Clown) Joke() {
fmt.Println("I'm funny")
}
func (c Clown) Jump() {
fmt.Println("And up I go")
}
A Clown
可以打招呼,跳跃和开玩笑,因此它实现了我们所有的接口。鉴于以下四个功能:
func PersonSayHello(p Person) {
p.Hello()
}
func JumperJump(j Jumper) {
j.Jump()
}
func JokerJoke(j Joker) {
j.Joke()
}
func EntertainerEntertain(e Entertainer) {
e.Joke()
e.Jump()
}
您可以将a传递Clown
给其中任何一个:
func main() {
c := Clown{}
PersonSayHello(c)
JokerJoke(c)
JumperJump(c)
EntertainerEntertain(c)
}
这是使用上面的代码转到Go Playground的链接。
最后一件事–您可能会这样争论:“但是,如果我以后对进行更改Person
,它将不会反映在其他界面中。” 的确,您必须手动进行这种调整,但是编译器会告知您。
如果具有此功能:
func JumperSayHello(j Jumper) {
PersonSayHello(j)
}
您的代码将正常工作。但是,如果向中添加另一个方法Person
,则依赖于a Jumper
是a 的事实的代码Person
将不再编译。用
type Person interface {
Hello()
Think()
}
你得到
。\ main.go:18:在PersonSayHello的参数中不能将j(跳线类型)用作Person类型:
跳线未实现Person(缺少Think方法)
只要您在 任何地方 都有依赖于a Jumper
始终为a
的事实的代码,就属于这种情况Person
。而且,如果您不这样做,即使在测试中也没有,那么-也许,跳线不认为实际上并不重要?
但是,如果无论出于何种原因,无论您对这些接口进行了什么更改,您实际上都需要确保a Jumper
始终为a
Person
,但实际上并没有在任何地方使用此事实,则始终可以为此目的创建代码:
package main
type Person interface {
Hello()
}
type Jumper interface {
Hello()
Jump()
}
// this function is never used, it just exists to ensure
// interface compatibility at compile time
func ensureJumperIsPerson(j Jumper) {
var p Person = j
_ = p
}
func main() {
}
问题内容: 我在网上搜索,但没有找到与i18n和Go相关的任何内容。 我希望使用Go来开发网站。处理国际化的最佳方法是什么? 问题答案: go-i18n具有一些不错的功能: 实施CLDR复数规则。 对带变量的字符串使用文本/模板。 翻译文件是简单的JSON。
问题内容: 我是Go编程的新手,我想知道:处理Go程序的配置参数的首选方法是什么(在其他情况下,可能会使用 属性 文件或 ini 文件的东西)? 问题答案: 该JSON格式为我工作得很好。标准库提供了编写缩进数据结构的方法,因此可读性很强。 另请参阅此golang-nuts线程。 JSON的好处在于,它在提供列表和映射语义时(它可能变得非常方便),解析起来相当容易并且易于人类阅读/编辑(这对于许多
在这种情况下,“可选”是什么意思? 最后一行注释“//可选”:这是什么意思?我试图通过实现一个集合,来实现一个集合,它完全不是可选的。 我需要实现所有的方法,即使是那些被评论为“可选”的方法。我显然不明白他们所说的“可选”是什么意思。对此有什么见解吗?
是否有人使用RecyclerView找到了将onClickListener设置为RecyclerView中的项的方法? 请帮帮我...我是初学者:)
Go语言中是否有枚举的简单实现?像下面这样的东西?
问题内容: mapArray是float32的2D切片。我对其进行了复制,因此 无需修改mapArray即可进行复制 。但是,事实并非如此。分配一个值进行修改。 这样做将使-1而不是其原始值。 如何制作切片的真实独立副本? 谢谢。 编辑: 问题答案: 2D切片是切片的切片。在您的函数中,您分配一个切片来容纳其他切片,然后为每个切片分配内存来容纳该行数据。要复制它,您需要复制所有这些数据行以及整个切