使用匿名结构进行合成与继承

时间:2018-10-26 06:46:41

标签: go inheritance composition

我正在读this slideshow,上面写着:

var hits struct {
    sync.Mutex
    n int
}

hits.Lock()
hits.n++
hits.Unlock()

那是如何工作的?似乎hits不是由组成互斥锁和整数,但是 是互斥锁和整数?

3 个答案:

答案 0 :(得分:3)

是构图。使用匿名字段(嵌入式字段),包含的结构将具有嵌入式类型的值,您可以引用它:不合格的类型名称充当字段名称。

所以您可以轻松地编写:

hits.Mutex.Lock()
hits.n++
hits.Mutex.Unlock()

嵌入类型时,嵌入类型的字段和方法会被提升为提升,因此无需指定字段名称(即嵌入类型名称)就可以引用它们。语法糖。引用自Spec: Selectors:

  

选择器f可以表示类型为f的字段或方法T,或者可以引用嵌套{{3 }},共f

除字段/方法提升之外,嵌入类型的embedded field也将包含嵌入类型的方法集。引用自method set

  

鉴于结构类型为TSpec: Struct types: S,在该方法的方法集中包含了改进的方法,如下所示:

     
      
  • 如果T包含嵌入字段S,则T的{​​{3}}和S都包括接收者{{1} }。 *S的方法集还包括使用接收者T的提升方法。

  •   
  • 如果S包含一个嵌入字段* T,则S和* S的方法集都包括带有接收者T或* T的提升方法。

  •   

这不是面向对象的继承,而是类似的东西。当您要实现接口时,这很方便:如果您嵌入了已经实现该接口的类型,那么您的struct类型也将嵌入。您还可以提供一些方法的自己的实现,这给人一种方法被覆盖的感觉,但是请不要忘记,表示嵌入类型的方法的选择器将获得嵌入值作为接收者(而不是嵌入器值),并且表示您在struct类型上定义的方法的选择器(可能会“隐藏”嵌入式类型的方法,也可能不会)将嵌入程序的struct值作为接收器。

答案 1 :(得分:0)

这称为嵌入,hitssync.Mutexint组成。这应该是正确的,因为Go中确实没有继承。成员与结构之间的关系更多是“具有”关系,而不是“是”关系。

Read here for a more complete explanation

从链接引用

  

嵌入类型的方法是免费提供的

这意味着您可以像hits.Lock()那样访问它们,而不必使用较长的形式hits.Mutex.Lock(),因为函数Lock()并不明确。

答案 2 :(得分:0)

请参见fmt.Printf("%#v\n", &hits) // &struct { sync.Mutex; n int }{Mutex:sync.Mutex{state:0, sema:0x0}, n:1} 变量的Go语法表示形式:

hits.Mutex.Lock()
hits.Mutex.Unlock()

声明变量时,它只是使用默认值初始化struct中的字段。

此外,编译器会自动将嵌入式结构的名称设置为字段。因此,您也可以像这样访问:

sync.Mutex

您可以访问{{1}}的所有方法和导出字段(如果有)。