组合式继承
code
package main
import (
"fmt"
)
type People struct{}
func (p *People) ShowA() {
fmt.Println("showA")
p.ShowB()
}
func (p *People) ShowB() {
fmt.Println("showB")
}
type Teacher struct {
People
}
func (t *Teacher) ShowB() {
fmt.Println("teacher showB")
}
func main() {
t := Teacher{}
t.ShowA()
}
运行结果:
showA
showB
在调用t.ShowA()
时,会先在t
的类型中查找ShowA()
方法
- 找到
ShowA()
方法后,直接调用 - 未找到
ShowA()
方法,则去t
的嵌入类型查找,在People
找到,在底层进行转换是(&(t.People)).ShowA()
,也就是(*People).showA(&(t.People))
后续在ShowA()
中调用ShowB()
时,会先在t
的类型中查找ShowB()
方法,也就是People
中查找,找到后,调用People
的ShowB()
方法
ps: 个人认为这是比较垃圾的代码,只应该出现在面试题中,不应该出现在实际代码中
一般开发都是基于接口
,去做组合式继承
,其次不要进行隐式转换/调用
,正常应该是t.People.ShowA()
如果面试官反问你怎么从People
中反调到Teacher
中的ShowB()
方法,建议先给他个大逼兜,让他说下为啥要这样做
可以考虑定义showB() 接口
,在people中定义该接口对象,通过show
对象调用方法showB()
type Show interface {
ShowB()
}
type People struct {
show Show
}
go tool compile -l -p main main.go --> main.o
go tool nm main.o |grep `T` |grep People
extra
B
只有Value()
方法,因为内部是A
,而A
的相关函数都是值传递
,无法拿到实际地址
,所以Set()
方法的生成就不需要了