2016-05-16 57 views
1

我試圖達到多態性這種方式GO多態性GO接口

type Discoverer interface { 
    Discover() string 
} 

type A struct { 
} 

func (obj A) GetTest() string { 
    return "im in A" 
} 

type B struct { 
    A 
} 

func (obj B) GetTest() string { 
    return "im in B" 
} 

func (obj A) Discover() string { 
    return obj.GetTest() 
} 

func main() { 
    a := A{} 
    b := B{} 

    fmt.Println(a.Discover()) 
    fmt.Println(b.Discover()) 
} 

現在我得到的輸出

im in A 
im in A 

所以,我的問題是:這是可能的見輸出

im in A 
im in B 

沒有「覆蓋」發現B?

func (obj B) Discover() string { 
    return obj.GetTest() 
} 

爲什麼?我有很多的結構小方法(類),發現漂亮的所有結構是相同的,所以我想避免複製粘貼&發現在每個結構(類)

去操場https://play.golang.org/p/nYc2hc3UbG

謝謝提前!

+1

Go中沒有繼承(也沒有多態性)。一些相關/可能的重複:[one](http:// stackoverflow。它是可能調用重寫方法從父結構在Golang),[two](http://stackoverflow.com/questions/30622605/can-embedded -struct-method-have-knowledge-of-parent-child),[three](http://stackoverflow.com/questions/29390736/go-embedded-struct-call-child-method-instead-parent-method) ,[四](http://stackoverflow.com/questions/29144622/what-is-the-idiomatic-way-in-go-to-create-a-complex-hierarchy-of-structs)。 – icza

回答

7

不可以。您在B中嵌入AB對於Discover沒有定義,因此總是調用A上的版本。該方法有一個A類型的接收器和A沒有意識到B或它嵌入在B中的事實。因此A只能調用它自己的版本GetTest()

B滿足發現接口的唯一原因是因爲它嵌入了A。它間接實現它。如果您需要B上的功能,則必須在B上對其進行定義。這完全不是多態,而是組合。 B不是ABA。如果你想要多態,你可以使用接口並實現它們。 B是可發現的,但僅僅因爲它有一個A

我會假設這僅僅是一個例子,但你實際上沒有理由甚至沒有這個Discovery方法。您的界面應該只需要GetTest。不要將嵌入與繼承混淆。 Go中沒有繼承。如果你想通過實現接口來實現多態行爲,並且你不能像這樣去掉角落,因爲嵌入類型和embeddor之間的關係不是繼承關係,所以沒有基類或「覆蓋」。

+0

好的,這就是我想要實現的,也許你可以讓我知道我如何在GO中做到這一點? https://play.golang.org/p/sqF9nxQBBW 它是返回對象的類工廠取決於用戶輸入(真正的配置文件),然後我必須填充結構myStruct並將其保存到數據庫。 –

1

要加上@evanmcdonnal的觀點,嵌入既不是繼承也不是多態。繼承恰好是一種便利,您可以免費獲得接口的實現,但是在Go中,它是明確的。正如@evanmcdonnal所指出的,嵌入可能看起來像繼承,但不是。

相反,您應該將概念多態性從繼承,嵌入和繼承中分離出來。大多數面向對象的語言並沒有進行比較。作爲一個例子,下面是一個多態的實現。請注意,Discover需要一個接口,並且AB實現了接口,使得該函數本身具有多態性。

package main 

import "fmt" 

type A struct{} 
type B struct{} 

type Test interface{ 
    GetTest() string 
} 

func (a *A) GetTest() string { 
    return "i am in A" 
} 

func (b *B) GetTest() string { 
    return "i am in B" 
} 

func Discover(t Test) string { 
    return t.GetTest() 
} 

func main() { 
    a := &A{} 
    b := &B{} 

    fmt.Println(Discover(a)) 
    fmt.Println(Discover(b)) 
} 
+0

請在@evanmcdonnal回答中尋找評論,這裏有我正在嘗試做的事情。 –

+2

我會避免在代碼中使用像'BaseClass'和'DerivedClass'這樣的名字。它使得它更加令人困惑,因爲在Go中沒有類和繼承。如果你打破了不同'GetValue'方法的實現,你可以用它們組成一個更大的'struct'。這將是一種可以模仿你想要的行爲的方式。 –