假设我有两只宠物,一只名叫露西的猫和一只名叫Fido的狗。我教过他们同样的伎俩,“说”。
将来我想获得更多的宠物,并教他们不同的技巧,所以在期待中,我已编码到一个界面:
package main
import "fmt"
type Pet interface {
speak() string
}
type Dog struct {
speech string
}
type Cat struct {
speech string
}
func (c Cat) speak() string {
return c.speech
}
func (d Dog) speak() string {
return d.speech
}
func getSpeech(p Pet) string {
return p.speak()
}
func main() {
Fido := Dog{"woof"}
Lucy := Cat{"meow"}
fmt.Println("Fido says:", getSpeech(Fido)) // Fido says: woof
fmt.Println("Lucy says:", getSpeech(Lucy)) // Lucy says: meow
}
现在,虽然效果很好,但似乎不必要地冗长。我显然在重复自己。另外,假设所有Dogs都说“woof”并且所有Cats都说“喵”,那么在结构体内初始化字符串是否惯用?
在不失去界面优势的情况下,您如何将此代码重新计算为更干燥?
答案 0 :(得分:6)
第一:我看不到你的代码中有任何重复:你有猫和狗,每只猫可能会说些什么,而每只狗都可以。如果情况并非如此,那么您的假设是正确的
如果所有的狗狗和所有的猫都喵喵叫:
const dogTalk = "woof"
func (d Dog) speak() string { return dogTalk; }
// or even
func (d Cat) speak() string { return "meow"; }
(并且:不要在Go中编写Java代码)
答案 1 :(得分:5)
您可以在某些情况下嵌入基本类型以委派常用字段和方法。这不是继承,它只是通过组合自动委托的一种形式。不要像使用java风格的OOP语言那样尝试使用它来创建类型层次结构。
您可以在此处将speak
方法委托给Speaker
类型。在实践中,这不太有用,因为Speaker
及其方法与嵌入它们的结构没有关系,即说话者不知道它所说的是哪种类型,也不知道哪个单独的实例。
https://play.golang.org/p/Bof92jZsNh
type Speaker struct {
Saying string
}
func (s Speaker) speak() string {
return s.Saying
}
type Pet interface {
speak() string
}
type Dog struct {
Speaker
}
type Cat struct {
Speaker
}
func getSpeech(p Pet) string {
return p.speak()
}
func main() {
Fido := Dog{Speaker{Saying: "woof"}}
Lucy := Cat{Speaker{Saying: "meow"}}
fmt.Println("Fido says:", getSpeech(Fido)) // Fido says: woof
fmt.Println("Lucy says:", getSpeech(Lucy)) // Lucy says: meow
}
答案 2 :(得分:0)
您可以这样做。
package main
import "fmt"
type Pet interface{ speak() string }
type Speaker struct{ Saying string }
func (s Speaker) speak() string { return s.Saying }
func getSpeech(p Pet) string { return p.speak() }
func main() {
Fido := Speaker{Saying: "woof"}
Lucy := Speaker{Saying: "meow"}
fmt.Println("Fido says:", getSpeech(Fido)) // Fido says: woof
fmt.Println("Lucy says:", getSpeech(Lucy)) // Lucy says: meow
}
我尽量不要使代码过于干燥。我对重复两次的代码还可以,并且只有在第三次重复时才考虑因素。