从另一个包导入结构时的私有嵌入结构

dtg*_*dtg 8 encapsulation embedding go

我有一个项目依赖于从另一个包导入的结构,我将其称为TheirEntity.

在下面的示例中,我(咳咳)嵌入TheirEntityMyEntity,它是 的扩展TheirEntity,并添加了功能。

但是,我不想TheirEntityMyEntity结构中导出,因为我宁愿消费者不TheirEntity直接访问。

我知道 Go 嵌入与经典 OOP 中的继承不同,所以这可能不是正确的方法,但是是否可以将嵌入结构指定为“私有”,即使它们是从另一个包导入的?如何以一种更惯用的方式实现同​​样的事情?

// TheirEntity contains functionality I would like to use...

type TheirEntity struct {
    name string
}

func (t TheirEntity) PrintName() {
    fmt.Println(t.name)
}

func NewTheirEntity(name string) *TheirEntity {
    return &TheirEntity{name: name}
}

// ... by embedding in MyEntity

type MyEntity struct {
    *TheirEntity // However, I don't want to expose 
                 // TheirEntity directly. How to embed this
                 // without exporting and not changing this
                 // to a named field?

    color        string
}

func (m MyEntity) PrintFavoriteColor() {
    fmt.Println(m.color)
}

func NewMyEntity(name string, color string) *MyEntity {
    return &MyEntity{
        TheirEntity: NewTheirEntity(name),
        color:       color,
    }
}
Run Code Online (Sandbox Code Playgroud)

jub*_*0bs 16

自从提出这个问题以来,Go 1.9就在该语言中添加了类型别名。通过非常规地使用类型别名,您实际上可以鱼与熊掌兼得!

首先,为您希望嵌入到结构中的第三方类型声明一个未导出的别名:

type theirEntity = TheirEntity
Run Code Online (Sandbox Code Playgroud)

然后,只需嵌入该别名而不是原始类型:

type MyEntity struct {
    *theirEntity
    color string
}
Run Code Online (Sandbox Code Playgroud)

游乐场


小智 5

像这样:

type MyEntity struct {
    *privateTheirEntity
}

type privateTheirEntity struct {
    *TheirEntity
}
Run Code Online (Sandbox Code Playgroud)


Vol*_*ker 3

[I]是否可以将嵌入结构指定为“私有”,即使它们是从另一个包导入的?

不。

如何以一种更惯用的方式实现同​​样的事情?

通过不嵌入但使其成为未导出的命名字段。

  • 我也这么怀疑。命名字段的缺点是,在这种情况下,我必须在“MyEntity”中实现多个函数,作为“irEntity”实现的多个接口的契约的一部分。嵌入使我能够满足该契约而无需重新实现。 (2认同)