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

时间:2017-12-08 13:52:17

标签: inheritance go modeling

我即将开始编写一个新的应用程序,我正在考虑在Go中编程,我没有经验。由于Go不支持继承,我如何忠实地将这样的域名转换为Go,同时仍然符合Go的哲学?:

  • 一个人有两条腿和两条胳膊,可以走路。
  • 音乐家是一个人,有乐器可以播放,有分区并可以阅读。但是没有人可以只是一个音乐家,就像音乐家一样,并且扮演着特定的乐器。
  • 一个大提琴手是一个有大提琴并可以演奏大提琴的音乐家
  • 钢琴家是一位有钢琴并可以弹钢琴的音乐家。
  • 当一个大提琴手/钢琴家走在街上时,每个人都只把他视为一个人。

也许我们可以像这样重新制定域名以删除任何'是'关系,以便它可以翻译成Go:

  • 小提琴手有人,音乐家,小提琴,可以拉小提琴
  • 小提琴家/钢琴家的音乐家部分有分区,可以阅读
  • 当小提琴家/钢琴家走在街上时,每个人都只能看到他的人物

在转换为Go之前,最好的做法是建模这样的域名吗?当Go的作者决定在Go中排除继承时,它是否想要让Go的作者想要他们的用户?

2 个答案:

答案 0 :(得分:4)

这不是“Go的作者希望他们的用户拥有的方式”; Go没有继承,因为它不是面向对象的语言,就像C没有继承一样。

它确实有组合和接口,你只需要对你所描述的内容进行建模:“拥有”其他对象的对象应该具有该类型的字段(组合),以及“可以”的对象执行某些操作可以通过界面建模。

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

答案 1 :(得分:1)

Go只有另一种观点。您可以考虑它们匹配的对象和接口。它离你的第二句话更近了:

  

小提琴手有人,音乐家,小提琴,可以拉小提琴

这是界面Musician - 它描述了具有方法Play()

的任何人
type Musician interface {
    Play()
}

对于exapmple结构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方式,而是Go-way。

  

当小提琴家/钢琴家走在街上时,每个人都只能看到他的人物部分

我们可以定义一个Walker界面的方式相同 - 可以走街道并且有适当方法Walk的人:

type Walker interface {
    Walk()
}

这是一种鸭子打字:在我们的生活中,如果一个人可以玩,它可以被带到整体。在Go语句中,如果一个人有方法Play(),则可以将其分配给音乐家类型变量。

  

接下来,您可以创建一个嵌入这两者的组合界面:

type WalkingMusician interface {
    Musician
    Walker
}

这描述了一个可以随时玩耍和行走的人。

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

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