11

编辑++:

如何不在 Go 中重复我的代码?

type Animal interface {
    Kingdom() string
    Phylum() string
    Family() string
}

type Wolf struct {}
type Tiger struct {}

func (w Wolf) Kingdom() string {return "Animalia"}
func (w Wolf) Phylum() string {return "Chordata"}
func (w Wolf) Family() string {return "Canidae"}

我为 type 实现了三个方法Wolf,我需要实现Tigertype 的所有方法来实现接口。但是KingdomPhylum两种类型的方法都是相同的。是否有可能只FamilyTiger类型实现方法:

func (t Tiger) Family() string {return "Felidae"}

而不是为每种类型重复所有三种方法?

免责声明

请不要与方法中的简单字符串返回混淆,在实际情况下,我需要不同的方法实现,而不仅仅是预定义的值。使用这种愚蠢的风格,我想避免玷污你的大脑。所以跳过方法根本不是办法。谢谢

4

3 回答 3

14

这是经典的作文:

type Wolf struct {
    Animalia
    Chordata
    Canidae
}
type Tiger struct {
    Animalia
    Chordata
    Felidae
}

type Animalia struct{}

func (Animalia) Kingdom() string { return "Animalia" }

type Chordata struct{}

func (Chordata) Phylum() string { return "Chordata" }

type Canidae struct{}

func (Canidae) Family() string { return "Canidae" }

type Felidae struct{}

func (Felidae) Family() string { return "Felidae" }

func main() {
    w := Wolf{}
    t := Tiger{}
    fmt.Println(w.Kingdom(), w.Phylum(), w.Family())
    fmt.Println(t.Kingdom(), t.Phylum(), t.Family())
}

游乐场: https: //play.golang.org/p/Jp22N2IuHL

于 2016-10-25T14:10:40.247 回答
4

这看起来很像对接口的滥用。接口不是类的替代品;它们是类型可以什么的表达。您在这里拥有的是数据。将数据存储在结构中。

type Animal struct {
    kingdom string
    phylum  string
    family  string
}

var wolf = Animal{"Animalia", "Chordata", "Canidae"}
var tiger = wolf
tiger.family = "Felidae"
于 2016-10-25T14:08:51.040 回答
3

由于我对该功能感兴趣,因此我阅读了一些有关该主题的文章并将其汇总到几个参考点。

嵌入

该功能名为“嵌入”。它解决了重复方法实现的问题。基本语法:

type Person struct {
    Name string
}

type Speaker struct { // Speaker is an abstract concept it has no name
    *Person // There is a type without field name. It is Anonymous.
}

包装和装饰

是的,没有 OOP,但代码无论如何都必须是 DRY。考虑该功能的最清晰方法是将其视为使用方法包装结构。所以描述匿名字段最真实的方式是“装饰器”模式(Pythonistas 众所周知)。

func (a *Speaker) Introduce(){ // But speaker can introduce itself
    fmt.Println(a.Name) // We have direct access to a wrapped struct attributes.
}

合并和覆盖

我们也可以组合在结构上实现的方法

func (s Speaker) Speak() string {
    return "Blah-blah"
}

type Den struct { // Combine Person and Speaker under Den struct
    Person
    Speaker
}

func (d Den) Speak() string { // Override Speak method only for Dennis 
    return "I'm quit!"
}

func main() {
    den := Den{Person: Person{Name: "Dennis",}}
    mike := Speaker{Person: Person{Name: "Michael",}}

    fmt.Println(den.Introduce())
    fmt.Println(den.Speak())
    fmt.Println(mike.Introduce())
    fmt.Println(mike.Speak())
}

通过这种方式,我们可以避免为每种类型实现每个必需的方法。

接口

接口也一样。但是如果将多个接口组合在一起,就意味着我们不需要声明已经在使用的接口中声明的方法。

操场

Dennis Suratna 的博客文章

文档

于 2016-10-26T11:49:35.690 回答