The Go Programming Language
› http://golang.org/
› Go Playground
Go Projects
› Revel Web Framework
croz

请教一个 go struct 的问题

  •  
  •   croz · May 2, 2017 · 2583 views
    This topic created in 3478 days ago, the information mentioned may be changed or developed.
    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()方法吗

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

    使用`interface`可以解决你的需求。
    x8
    x8
    May 2, 2017❤️1
    3
    加一个方法

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

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

    你需要 interface
    zhujinliang
    zhujinliang
    May 2, 2017❤️1
    7
    还有种方法

    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()
    }
    Immortal
    Immortal
    May 2, 2017❤️1
    9
    重载 Child 的 A 方法
    chlid.A()会调用到 child 的 A 方法
    child.parent.A()会调用到 parent 的 A 方法
    jarlyyn
    jarlyyn
    May 2, 2017❤️1
    10
    个人觉得,go 没有 oop ……

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

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

    而非写作方法本身。

    也就是 不是 p.A(),c.A()
    而是 A(p),A(c)
    scnace
    scnace
    May 2, 2017❤️1
    11
    2L 正解 贴下实现,顺便贴下实现(不是很喜欢这么写),https://play.golang.org/p/6NcQ45ai8v
    Immortal
    Immortal
    May 2, 2017❤️1
    13
    @jarlyyn 其实原理和你说的是基本一样的 p.A()和 A(p) 记得 go 笔记那本书里有写
    hilow
    hilow
    May 2, 2017
    14
    @zhujinliang 厉害了
    croz
    croz
    OP
    May 3, 2017
    15
    学习了楼上给出的方法,非常感谢
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1072 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 53ms · UTC 18:18 · PVG 02:18 · LAX 10:18 · JFK 13:18
    ♥ Do have faith in what you're doing.