V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
croz
V2EX  ›  Go 编程语言

请教一个 go struct 的问题

  •  
  •   croz · 2017-05-02 16:07:13 +08:00 · 1540 次点击
    这是一个创建于 2760 天前的主题,其中的信息可能已经有所发展或是发生改变。
    type Parent struct{}
    
    func (p *Parent) A() {
    	p.B()
    }
    
    func (p *Parent) B() {
    	fmt.Println("parent.B()")
    }
    
    type Child struct {
    	Parent
    }
    
    func (c *Child) B() {
    	fmt.Println("child.B()")
    }
    
    

    定义了两个结构体,Parent 和 Child
    Parent 有 A()和 B()两个方法,在 A 中调用了 B
    Child 只实现了 B(),然后按如下方式调用:

    func main() {
    	p := &Parent{}
    	c := &Child{}
    	p.A()
    	c.A()
    	c.Parent.A()
    }
    

    发现 c.A()和 c.Parent.A()都只调用到了 Parent 的 B()方法
    有办法可以在 A()方法中调用到 Child 的 B()方法吗

    第 1 条附言  ·  2017-05-03 10:05:43 +08:00
    感谢各位的回复,所以说应该是 go 的语法特性,不能这样使用吧。楼上各位已一一感谢,就不艾特了
    15 条回复    2017-05-03 10:16:13 +08:00
    Kilerd
        1
    Kilerd  
       2017-05-02 16:44:36 +08:00 via iPhone   ❤️ 1
    不可能吧?!
    shadowind
        2
    shadowind  
       2017-05-02 16:59:41 +08:00   ❤️ 2
    go 的嵌套不会重载,所以都是`Parent`的`B()`方法。

    使用`interface`可以解决你的需求。
    lizon
        3
    lizon  
       2017-05-02 18:15:53 +08:00   ❤️ 1
    加一个方法

    func (c *Child) A() {
    c.B()
    }

    调什么方法得看方法绑定的指针类型
    sumhat
        4
    sumhat  
       2017-05-02 18:32:28 +08:00   ❤️ 1
    Golang 中 Parent 不知道 Child 的存在,一旦调用了 Parent 的方法,之后所有的调用都局限在 Parent 中。
    bianhua
        5
    bianhua  
       2017-05-02 18:38:23 +08:00   ❤️ 1
    @sumhat 其实可以解释的更简单一点:Golang 没有 Override。之所以 c.A()能运行,仅仅是因为这是一种语法糖。实际上 c.A()跟 c.Parent.A()是等价的。
    rrfeng
        6
    rrfeng  
       2017-05-02 18:41:40 +08:00   ❤️ 1
    楼上已经回答的很清楚了。
    不过即使是在支持重载的语言中这个写法也不怎么优雅吧?

    你需要 interface
    zhujinliang
        7
    zhujinliang  
       2017-05-02 18:49:11 +08:00   ❤️ 1
    还有种方法

    package main

    import "fmt"

    type CanB interface {
    B()
    }

    type Parent struct {
    instance CanB
    }

    func (p *Parent) A() {
    p.B()
    }

    func (p *Parent) B() {
    if p.instance != nil {
    p.instance.B()
    return
    }
    fmt.Println("parent.B()")
    }
    func (p *Parent) SetInstance(i interface{}) {
    if inst, ok := i.(CanB); ok {
    p.instance = inst
    }
    }

    type Child struct {
    Parent
    }

    func (c *Child) B() {
    fmt.Println("child.B()")
    }

    func main() {
    p := &Parent{}
    c := &Child{}

    c.SetInstance(c)

    p.A()
    c.A()
    c.Parent.A()
    }
    zhujinliang
        8
    zhujinliang  
       2017-05-02 18:49:39 +08:00   ❤️ 2
    Immortal
        9
    Immortal  
       2017-05-02 19:19:54 +08:00   ❤️ 1
    重载 Child 的 A 方法
    chlid.A()会调用到 child 的 A 方法
    child.parent.A()会调用到 parent 的 A 方法
    jarlyyn
        10
    jarlyyn  
       2017-05-02 19:24:30 +08:00   ❤️ 1
    个人觉得,go 没有 oop ……

    所谓的继承其实就是帮你自动调用嵌入结构的同名函数的语法糖。

    就我的角度来看,大部分的操作 需要一个外部函数 调用 interface 来处理。

    而非写作方法本身。

    也就是 不是 p.A(),c.A()
    而是 A(p),A(c)
    scnace
        11
    scnace  
       2017-05-02 19:31:56 +08:00   ❤️ 1
    2L 正解 贴下实现,顺便贴下实现(不是很喜欢这么写),https://play.golang.org/p/6NcQ45ai8v
    scnace
        12
    scnace  
       2017-05-02 19:32:33 +08:00
    Immortal
        13
    Immortal  
       2017-05-02 19:40:02 +08:00   ❤️ 1
    @jarlyyn 其实原理和你说的是基本一样的 p.A()和 A(p) 记得 go 笔记那本书里有写
    hilow
        14
    hilow  
       2017-05-02 21:15:54 +08:00
    @zhujinliang 厉害了
    croz
        15
    croz  
    OP
       2017-05-03 10:16:13 +08:00
    学习了楼上给出的方法,非常感谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   955 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 21:50 · PVG 05:50 · LAX 13:50 · JFK 16:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.