英文:
Golang override embedded functions
问题
我想知道在嵌套函数中是否有解决方案可以应用"多态性",其中一个指向另一个。例如,我有以下接口:
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") // 指向 Get
}
在其他实现中(例如测试),我想用其他的响应替换默认的 Get 函数,但保持 GetResource 方法不变:
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("DOESN'T WORK :(")
fmt.Println("Client GetRes:", c.GetResource())
fmt.Println("Test GetRes:", t.GetResource())
输出结果如下:
WORKS:
Client Get: Impl [aaa]
Test Get: Test [aaa]
DOESN'T WORK :(
Client GetRes: Impl [resource]
Test GetRes: Impl [resource]
如何使最后一个打印输出字符串 Test [resource]
?
你可以在这里查看 Go Playground 示例:https://play.golang.org/p/b-vM1_W3oB
英文:
I wonder if is there solution for apply "polymorphism" in embedded functions when one pointing to other. For example I have following interface:
type Client interface {
Get(string) string
GetResource() string
}
and default implementation:
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
}
And in other implementation (tests for example) I want to replace default Get function with other response but leave GetResource method untouched
type TestImpl struct {
ClientImpl
}
func (t TestImpl) Get(s string) string {
return fmt.Sprintf("Test [%s]", s)
}
Override function works when it's called directly but doesn't when called from embedded function. Look output produced from following test case:
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]
How to make last print to output string Test [resource]
?
Go Playground example: https://play.golang.org/p/b-vM1_W3oB
答案1
得分: 2
在你的示例中,你需要将Get
函数隔离到自己的接口中。
以下是两种类似的实现方式:
// 第一种方式:
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)
}
// 编写一个裸的GetResource函数:
func GetResource(c Getter) string {
return c.Get("resource")
}
// 第二种方式:将"Getter"作为一个字段存储在结构体中
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)
}
// 创建一个结构体,其中包含一个Getter,并具有使用它的方法:
type Client struct {
Getter
}
func (c *Client) GetResource() string {
return c.Get("resource")
}
英文:
In your example, you need to isolate the Get
function in its own interface.
Here are two similar ways to do this :
// 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")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论