Uber Go 语言编程规范:避免在公共结构体中嵌入类型

这些嵌入的类型会 泄露实现细节,阻止类型演变,并模糊文档。

假设您已经使用一个共享的AbstractList,实现了各种列表类型,避免在具体的列表实现中嵌入AbstractList,相反的,只手写那些将会委托给抽象列表的具体列表中的方法。

type AbstractList struct {}

//以下是定义公共结构体的方法

// Add adds an entity to the list.
func (l *AbstractList) Add(e Entity) {
  // ...
}

// Remove removes an entity from the list.
func (l *AbstractList) Remove(e Entity) {
  // ...
}

Bad

// ConcreteList 是一个列表实体.
type ConcreteList struct {
  *AbstractList
}

Good

// ConcreteList 是一个实体列表.
type ConcreteList struct {
  list *AbstractList
}

//以下方法都是委托给抽象列表实现

// Add adds an entity to the list.
func (l *ConcreteList) Add(e Entity) {
  l.list.Add(e)
}

// Remove removes an entity from the list.
func (l *ConcreteList) Remove(e Entity) {
  l.list.Remove(e)
}

GO语言允许type embedding ,作为在继承和组合之间的一种折衷方案。外部类型 会获取嵌入类型方法的隐式的副本,默认情况下,这些方法会委托给嵌入实例的相同的方法去实现。

该结构体还会获得一个与类型同名的字段。因此,如果的嵌入的类型是Public的,那么这个字段也是Public的,为了保持向后兼容性,外部类型的每一个未来版本都必须保持这个嵌入的类型。

嵌入的类型很少是必需的。但是,它可以帮助您避免编写冗长的委托方法。

即使是嵌入一个兼容的AbstractList接口,而不是一个结构体,也会为开发人员提供更多的灵活性,以便在将来进行改变。但是,此种方式,仍然泄露了具体列表使用抽象实现的细节。

Bad

// AbstractList 是一个通用的实现针对各种类型的实体列表
type AbstractList interface {
  Add(Entity)
  Remove(Entity)
}

// 具体实现的List
type ConcreteList struct {
  AbstractList
}

Good

// ConcreteList 具体列表的实现.
type ConcreteList struct {
  list AbstractList
}

//只实现委托给AbstractList中的方法
// Add adds an entity to the list.
func (l *ConcreteList) Add(e Entity) {
  l.list.Add(e)
}

// Remove removes an entity from the list.
func (l *ConcreteList) Remove(e Entity) {
  l.list.Remove(e)
}

无论是使用嵌入结构体还是嵌入接口,嵌入的类型都限制了类型的发展演化。

  • 向嵌入的接口添加方法,是一个破坏性的更改。
  • 从嵌入的结构体中删除方法,是一个破坏性的更改。
  • 移除嵌入的类型是一个破坏性的更改。
  • 即使使用用满足相同接口的替代方案去替换嵌入的类型,也是一个破坏性的更改。

尽管编写这些委托的方法很繁琐,但额外的工作却隐藏了实现细节,留下了更多的更改机会,并且消除了在文档中发现完整列表接口的间接途径。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DreamCatcher

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值