2015-10-27 54 views
0

TL; DR請參見底部的操場鏈接。嵌入結構以覆蓋方法

我在Manager結構中定義了方法,其中包含ContextManager是版本化的,允許新版本只定義已更改的函數,並且如果它們未被重新定義,則自動使用舊版本中的函數。

type Context struct { ... } 

type Manager1 struct{ 
    Context Context 
} 

type Manager2 struct { 
    Manager1 
    Context Context 
} 

當調用未上Manager2限定在Manager2的函數Context爲零。有沒有辦法做到這一點上下文將可用?

這一實例說明問題比我能解釋一下: http://play.golang.org/p/gFe6GgUKEJ

回答

3

你濫用嵌入。事情是,你已經在Manager1上定義了Context,儘管你已經在每個後續類型上重新定義了它。在Manager3中,您正在設置它的值爲Context實例。當調用Hello()時,它在Manager2上定義並訪問它的Context實例,該實例沒有值。看看這個例子來證明http://play.golang.org/p/XebShA9ap4

錢就行是: m3 = Manager3{Manager2: Manager2{Context: Context{Value: "testing3"}}}

正如你可以看到,如果我實例化嵌入Manager3Manager2實例,並設置它的Context值它被打印出來。我會建議改變你的類型,以便Context僅在Manager1上定義,然後在初始化類型時使用類似於我的示例中的語法。

編輯:爲了把寫在評論中討論的設計,你會改變你的類型到這個;

type Context struct { 
    Value string 
} 

type Manager1 struct { 
    Context Context 
} 

type Manager2 struct { 
    Manager1 
} 

type Manager3 struct { 
    Manager2 
} 

刪除的Hello()實施上Manager2乾脆。然後更新你的複合文字初始化到這個;

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

我甚至可以說Manager2和Manager3根本不應該包含上下文:https://play.golang.org/p/YkxjPZ4Hm6。除非他們需要沒有獨特的價值。但是他們都需要實現這個功能。 – captncraig

+1

@ captncraig是的我以爲我在倒數第二段中提到了這一點。也許它不清楚。但是,是的,如果'Manager1'有一個'Context'實例,將相同的字段放入任何嵌入'Manager1'的東西是一個糟糕的設計。除了冗餘之外,這是該死的混亂! – evanmcdonnal

2

你誤會呼籲通過嵌入結構的嵌入式結構的方法:這只是語法糖!

你被允許縮寫m3.Manager2.Hello()m3.Hello()但你好方法永遠不會調用「的」 M3,但總是在嵌入式Manager2(其中有一個零的Contex)。

嵌入不允許「覆蓋方法」。嵌入不是子類,它只是語法糖。

0

您的Manager3結構包含多個Context成員 - 您正在設置Manager3.Context,但打印Manager2.Context。什麼,你可能尋找的是從Manager1Manager2去除冗餘Context成員和初始化結構是這樣的:

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

提供存取或工廠函數可能會使這一點更好。