嵌入结构以覆盖方法

时间:2015-10-27 21:21:43

标签: go

TL; DR 请参阅底部的游乐场链接。

我在Manager结构上定义了包含Context的方法。 Manager是版本化的,允许新版本仅定义已更改的函数,如果未重新定义,则自动使用旧版本的函数。

type Context struct { ... }

type Manager1 struct{
    Context Context
}

type Manager2 struct {
    Manager1
    Context Context
}

Manager2上调用未在Manager2上定义的函数时,Context为零。有没有办法在上下文可用的情况下执行此操作?

这个例子比我能解释的更好地展示了这个问题: http://play.golang.org/p/gFe6GgUKEJ

3 个答案:

答案 0 :(得分:3)

您滥用嵌入。问题是,您已经在@Html.ActionLink("New Child", "Create", new { id = item.Id }) 上定义了Context,尽管您已经在每个后续类型上重新定义了Manager1。在Manager3中,您需要为其Context实例设置值。当Hello()被调用时,它会在Manager2上定义,并访问它的Context实例,而该实例没有值。查看此示例以演示http://play.golang.org/p/XebShA9ap4

资金线是: m3 = Manager3{Manager2: Manager2{Context: Context{Value: "testing3"}}}

如您所见,如果我实例化Manager2中嵌入的Manager3实例并设置它的Context值,则会打印出来。我建议您更改类型,以便Context仅在Manager1上定义,然后在初始化类型时使用我的示例中的语法。

编辑:要将评论中讨论的设计改为书面形式,您可以将类型更改为此;

type Context struct {
    Value string
}

type Manager1 struct {
    Context Context
}

type Manager2 struct {
    Manager1
}

type Manager3 struct {
    Manager2
}

完全删除Hello()Manager2的实施。然后将composite-literal初始化更新为this;

m1 := Manager1{Context: Context{Value: "testing1"}}
m2 := Manager2{Manager1: Manager1{Context: Context{Value: "testing2"}}}
m3 := Manager3{Manager2: Manager2{Manager1: Manager1{Context: Context{Value: "testing3"}}}}

答案 1 :(得分:2)

你误解了通过嵌入结构调用嵌入式结构的方法:这只是语法糖!

您可以将m3.Manager2.Hello()缩写为m3.Hello(),但永远不会在“m3”上调用Hello方法,但始终在嵌入式Manager2上调用(具有nil Contex)。

嵌入不允许“覆盖方法”。嵌入不是子类化,它只是语法糖。

答案 2 :(得分:0)

您的Manager3结构包含多个Context成员 - 您正在设置Manager3.Context,但打印Manager2.Context。您可能正在寻找的是从ContextManager1中移除多余的Manager2成员并以这种方式初始化结构:

var (
    m1 = Manager1{Context: Context{Value: "testing1"}}
    m2 = Manager2{Manager1: Manager1{Context: Context{Value: "testing2"}}}
    m3 = Manager3{Manager2: Manager2{Manager1: Manager1{Context: Context{Value: "testing3"}}}}
)

此处的完整示例:http://play.golang.org/p/13DOYKWN5C

提供访问者或工厂功能可能会使这更好一些。