编码到Go中的接口而不重复自己

rid*_*elf 1 interface dry go

假设我有两只宠物,一只名叫露西的猫和一只名叫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
} 
Run Code Online (Sandbox Code Playgroud)

现在,虽然这很好用,但似乎不必要地冗长.我显然在重复自己.另外,假设所有Dogs都说"woof"并且所有Cats都说"喵",那么初始化结构中的字符串是不是惯用?

在不失去界面优势的情况下,您如何将此代码重新考虑为更干燥?

Vol*_*ker 6

第一:我看不到你的代码中有任何重复:你有猫和狗,每只猫都可以说些什么,每只狗都可以.如果情况并非如此,那么您的假设是正确的

如果所有的狗狗和所有的猫咪喵喵怎么样:

const dogTalk = "woof"
func (d Dog) speak() string { return dogTalk; }
// or even
func (d Cat) speak() string { return "meow"; }
Run Code Online (Sandbox Code Playgroud)

(并且:不要在Go中编写Java代码)


Jim*_*imB 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
}
Run Code Online (Sandbox Code Playgroud)