处理 Go 中缺乏继承的最佳实践

Best practices to deal with the lack of inheritance in Go

我正要开始编写一个新的应用程序,我正在考虑用 Go 编程,但我没有这方面的经验。由于 Go 不支持继承,我如何忠实地将这样的域翻译成 Go,同时仍然符合 Go 的哲学?:

也许我们可以像这样重新构造域以删除任何 'is a' 关系,以便它可以翻译成 Go:

在翻译成 Go 之前,像这样对这样的域建模是最佳实践吗?当 Go 的作者决定在 Go 中排除继承时,是否是 Go 的作者希望他们的用户拥有的思维方式?

不是"the way of thinking that the authors of Go want their users to have"; Go 没有继承,因为它不是面向对象的语言,就像 C 没有继承一样。

它确实有组合和接口,这是您对所描述的内容进行建模所需要的全部:一个对象 "has a" 其他对象应该具有该类型(组合)的字段,以及一个对象"can" 执行一些可以通过接口建模的操作。

但是,如果这个问题描述的是一个实际的编程问题而不是一个隐喻,那么它可能更容易回答;当然,除非您的应用程序打算模拟各种音乐家的肢体和乐器。

围棋有另一种观点。你可以想到它们匹配的对象和接口。第二句离你更近了:

A violinist has a person part, a musician part, a violin and can play the violin

这是接口 Musician - 它描述了任何拥有方法的人 Play()

type Musician interface {
    Play()
}

例如结构Violinist可以有这样的方法:

type Violinist struct {}
func (v Violinist) Play() {}

Pianist可以玩:

type Pianist struct {}
func (v Pianist) Play() {}

它们都匹配接口Musician。所以你可以有一个 musician 变量并将不同的音乐家分配给它:

var musician Musician
musician = Violinist{}
musician.Play()
musician = Pianist{}
musician.Play()

看看同一个变量如何改变它的行为。它和 Polyformism 一样,不是 OOP-way,而是 Go-way。

When a violinist/pianist is walking in the streets, everybody can only see his person part

我们可以用同样的方式定义一个 Walker 接口 - 可以走在街上并有适当的方法 Walk 的人:

type Walker interface {
    Walk()
}

这是一种鸭子打字:在我们的生活中,如果一个人可以演奏,就可以带到合奏中。在 Go 术语中,如果一个人有方法 Play(),它可以分配给音乐家类型变量。

Etc

接下来你可以制作一个嵌入这两者的组合界面:

type WalkingMusician interface {
    Musician
    Walker
}

形容一个人瞬间会玩会走路

var walkingMusician WalkingMusician
walkingMusician = walkingViolinist
walkingMusician.Walk()
walkingMusician.Play()

https://play.golang.org/p/ai-h4VDUpj