2017-04-06 40 views
-1

我想知道是否有解決方案適用於嵌入式函數中的「多態性」,當指向其他人。例如,我有以下接口:Golang覆蓋嵌入函數

type Client interface { 
    Get(string) string 
    GetResource() string 
} 

和默認實現:

type ClientImpl struct { 
} 

func (c ClientImpl) Get(s string) string { 
    return fmt.Sprintf("Impl [%s]", s) 
} 

func (c ClientImpl) GetResource() string { 
    return c.Get("resource") # points to Get 
} 

而在其他實現(測試爲例)我要替換默認獲取與其它響應函數,但留下佔用資源的方法不變

當它直接調用,但不會從嵌入式函數調用時
type TestImpl struct { 
    ClientImpl 
} 

func (t TestImpl) Get(s string) string { 
    return fmt.Sprintf("Test [%s]", s) 
} 

覆蓋功能的工作原理。

c := ClientImpl{} 
t := TestImpl{} 
fmt.Println("WORKS:") 
fmt.Println("Client Get:", c.Get("aaa")) 
fmt.Println("Test Get:", t.Get("aaa")) 
fmt.Println("DOSN'T WORK :(") 
fmt.Println("Client GetRes:", c.GetResource()) 
fmt.Println("Test GetRes:", t.GetResource()) 

# WORKS: 
# Client Get: Impl [aaa] 
# Test Get: Test [aaa] 
# DOSN'T WORK :(
# Client GetRes: Impl [resource] 
# Test GetRes: Impl [resource] 

如何使最終打印輸出字符串Test [resource]:瞧輸出下面的測試情況下產生的?

去遊樂場例如:https://play.golang.org/p/b-vM1_W3oB

+0

沒門。 – Volker

+0

好吧,所以我必須重複代碼或從客戶端界面提取獲取功能? – SZMER

+3

最好的建議是:不要試圖模仿嵌入式的「傳統OOP」。它只是不成功。如果你需要一個接口的測試實現:寫一個。 – Volker

回答

2

在你的榜樣,你需要在自己的接口來隔離Get功能。

這裏有兩個類似的方式來做到這一點: 「如何使最終打印輸出字符串測試[資源]」

// one way to do this : 
type Getter interface { 
    Get(string) string 
} 

type ClientImpl struct { 
} 

func (c ClientImpl) Get(s string) string { 
    return fmt.Sprintf("Impl [%s]", s) 
} 

type TestImpl struct { 
} 

func (t TestImpl) Get(s string) string { 
    return fmt.Sprintf("Test [%s]", s) 
} 

// write a bare GetResource function : 
func GetResource(c Getter) string { 
    return c.Get("resource") 
} 

https://play.golang.org/p/R2XciBx_yk

// another way : store the "Getter" as a field in a struct 
type Getter interface { 
    Get(string) string 
} 

type ProdGetter struct { 
} 

func (c ProdGetter) Get(s string) string { 
    return fmt.Sprintf("Impl [%s]", s) 
} 

type TestGetter struct { 
} 

func (t TestGetter) Get(s string) string { 
    return fmt.Sprintf("Test [%s]", s) 
} 

// create a struct, which holds a Getter, and has methods to do stuff with it : 
type Client struct { 
    Getter 
} 

func (c *Client) GetResource() string { 
    return c.Get("resource") 
} 

https://play.golang.org/p/ZMI5PlAo4L