douzhuican0041 2017-04-06 08:59
浏览 97

Golang覆盖嵌入式功能

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条回答 默认 最新

  • dongshengli6384 2017-04-06 10:03
    关注

    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")
    }
    

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

    评论

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料