请教一个 go struct 的问题

2017-05-02 16:07:13 +08:00
 croz
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()方法吗

1568 次点击
所在节点    Go 编程语言
15 条回复
Kilerd
2017-05-02 16:44:36 +08:00
不可能吧?!
shadowind
2017-05-02 16:59:41 +08:00
go 的嵌套不会重载,所以都是`Parent`的`B()`方法。

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

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

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

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

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
2017-05-02 18:49:39 +08:00
Immortal
2017-05-02 19:19:54 +08:00
重载 Child 的 A 方法
chlid.A()会调用到 child 的 A 方法
child.parent.A()会调用到 parent 的 A 方法
jarlyyn
2017-05-02 19:24:30 +08:00
个人觉得,go 没有 oop ……

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

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

而非写作方法本身。

也就是 不是 p.A(),c.A()
而是 A(p),A(c)
scnace
2017-05-02 19:31:56 +08:00
2L 正解 贴下实现,顺便贴下实现(不是很喜欢这么写),https://play.golang.org/p/6NcQ45ai8v
scnace
2017-05-02 19:32:33 +08:00
Immortal
2017-05-02 19:40:02 +08:00
@jarlyyn 其实原理和你说的是基本一样的 p.A()和 A(p) 记得 go 笔记那本书里有写
hilow
2017-05-02 21:15:54 +08:00
@zhujinliang 厉害了
croz
2017-05-03 10:16:13 +08:00
学习了楼上给出的方法,非常感谢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/358569

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX