为什么你想在Go语言中使用组合(composition)?

huangapple go评论87阅读模式
英文:

Why would you want to use composition in golang?

问题

在下面的代码中,我展示了我认为在Go语言中嵌入(其中方法被提升)和组合(其中方法不被提升)之间的区别。

为什么你会想要在Go语言中使用组合?

type obj1Inherited struct {
    obj2
}

type obj1Composed struct {
    someobj obj2
}

type obj2 struct {
}

func (o obj2) printTest() {
    fmt.Println("obj2")
}

func main() {
    o := obj1Inherited{}
    o.printTest() //fine - printTest is promoted

    obj1Composed := obj1Composed{}
    obj1Composed.someobj.printTest() //fine because I'm using the composed obj
    obj1Composed.printTest() //not fine - printTest is NOT promoted
}
英文:

In the following code I show what I think is the difference between embedding (where methods get promoted) and composition (where methods are not promoted) in golang.

Why would you ever want to use composition in golang?

type obj1Inherited struct {
    obj2
}

type obj1Composed struct {
    someobj obj2
}

type obj2 struct {
}

func (o obj2) printTest() {
    fmt.Println("obj2")
}

func main() {
    o := obj1Inherited{}
    o.printTest() //fine - printTest is promoted

    obj1Composed := obj1Composed{}
    obj1Composed.someobj.printTest() //fine because I'm using the composed obj
    obj1Composed.printTest() //not fine - printTest is NOT promoted

答案1

得分: 17

Effective Go中,值得仔细阅读关于嵌入的部分。

一个常见的例子是在结构体/映射中使用互斥锁。

type SafeStruct struct {
    SomeField string 
    *sync.Mutex
}

这样做比编写适当的包装函数(这样做很重复)或者使用 stutter(在这种情况下是 safe.mutex.Unlock())要容易得多。

使用嵌入的方式,你只需要这样做:

safe := SafeStruct{SomeField: "init value"}

safe.Lock()
defer safe.Unlock()
safe.SomeField = "new value"

这在你尝试在嵌入字段上使用多个函数(实现了像 io.ReadWriter 这样的接口)时尤其有用。

英文:

It is worth going over the section on Embedding in Effective Go.

A common example is having a struct/map with a Mutex.

type SafeStruct struct {
    SomeField string 
    *sync.Mutex
}

It is much easier to type

safe := SafeStruct{SomeField: "init value"}

safe.Lock()
defer safe.Unlock()
safe.SomeField = "new value"

than having to either write appropriate wrapper functions (which are repetitive) or have the stutter of

safe.mutex.Unlock()

when the only thing you would ever do with the mutex field is access the methods (Lock() and Unlock() in this case)

This becomes even more helpful when you are trying to use multiple functions on the embedded field (that implemement an interface like io.ReadWriter).

答案2

得分: 0

我想再提一点,关于你示例中的第一个情况。
如果obj1Inheritedobj2有一个同名的方法,那么从obj1Inherited实例调用的方法将始终执行obj1Inherited的方法。

要调用obj2的方法,你可以使用另一种方法,不要提升...

英文:

One more point I want to cover for first case in your example.
If obj1Inherited and obj2 have a same name method then that method call (from obj1Inherited instance) will always execute obj1Inherited method.

To call obj2 method you can use the other approach of not promoting

答案3

得分: 0

我会尝试回答原始问题 - 有时人们使用"composition"来代替嵌入以隐藏嵌入结构的功能。这不是一个很好的用例,但有时人们更喜欢这样做。

type Obj1composed struct {
  notExportedObj1 obj1
}

func NewObj1Composed(someParam Params) Obj1composed {
...
}

func (o Obj1Composed) Print() {
  // 这里进行一些繁重的计算。进行数十个API调用
  // 打印一些数据
}
英文:

I'll try to answer original question - sometimes people use "composition" instead of embedding to hide functionality of embedded struct. Not a great use case - but people prefer it sometimes.

type Obj1composed struct {
  notExportedObj1 obj1
}

func NewObj1Composed(someParam Params) Obj1composed {
...
}

func (o Obj1Composed) Print() {
  // Some heavy calculations here. Make Dozens of API calls
  // print some data
}

答案4

得分: 0

在Golang中,有3种类型的embed

  • 在结构体中嵌入结构体
  • 在接口中嵌入接口
  • 在结构体中嵌入接口

详细信息可以参考这篇文章:https://eli.thegreenplace.net/2020/embedding-in-go-part-1-structs-in-structs/

英文:

In Golang, there are 3 types of embed

  • struct embed in struct
  • interface embed in interface
  • interface embed in struct

In detail you can refer to this post: https://eli.thegreenplace.net/2020/embedding-in-go-part-1-structs-in-structs/

huangapple
  • 本文由 发表于 2016年4月19日 05:22:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/36704522.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定