前言
本文是探讨的是"go语言中的“继承”
"
此文章是个人学习归纳的心得, 为掘金首发 , 如有不对, 还望指正, 感谢!
判断是否有阅读本文的必要,可以先看下面的样例
样例一
package main
type student struct {
name string
id int
age int
}
func (s student) getName() string {
return s.name
}
type schoolOne struct {
student
}
type schoolTow struct {
s student
}
请问schoolOne和schoolTow有什么区别? 在调用getName方法上,有什么区别?
答案
schoolOne和schoolTow都是嵌入了结构体student,但是schoolOne是隐式嵌入,schoolTow是显示嵌入,给这个结构体重命名为s,
隐式嵌入会实现go的自动转发,类似于其他语言的继承,就是说schoolOne得到了student的getName方法。
go语言作为一门极简的语言,是没有类一说的,但是go通过结构体和转发实现了类似类和继承的效果。
在调用上的区别:
func main() {
One := &schoolOne{struct {
name string
id int
age int
}{name: "言志志", id: 666, age: 18}}
Tow := &schoolTow{struct {
name string
id int
age int
}{name: "言志志2", id: 999, age: 18}}
fmt.Printf("%v", One.getName())
fmt.Printf("%v", Tow.s.getName())
fmt.Printf("%v", One.student6.getName()) //还可以这样
}
其实就是说,如果是隐式的话,就会比较方便,因为你没有给定字段名,显式的话,要通过字段名来调用。
fmt.Printf("%v", Tow.student6.getName()) 会报错
报错是因为,你已经给了字段名了,这个隐式的转发,也就是go的自动转发。
关于字段的自动转发的测试
属性也会自动转发
package main
import "fmt"
type student struct {
name string
id int
age int
}
func (s student) getName() string {
return s.name
}
type schoolOne struct {
student
}
func main() {
One := &schoolOne{struct {
name string
id int
age int
}{name: "言志志", id: 666, age: 18}}
fmt.Printf("%v", One.id)
}
运行结果:
但是需要注意的,这个字段的首字母,我用的小写,所以只能在包内可以这样,其他包引用的话,即使是转发了,但是由于没有公开,你还是看不到效果的
父结构体和嵌入的子结构体重名
package main
import "fmt"
type student struct {
name string
id int
age int
}
func (s student) getName() string {
return s.name
}
type schoolOne struct {
name string
student
}
func (s schoolOne) getName() string {
return s.name
}
func main() {
One := &schoolOne{"言志志1号", struct {
name string
id int
age int
}{name: "言志志2号", id: 666, age: 18}}
fmt.Printf("One.name:%v n", One.name)
fmt.Printf("One.student6.name: %v n", One.student6.name)
fmt.Printf("One.getName(): %v n", One.getName())
fmt.Printf("One.student6.getName(): %v n", One.student6.getName())
}
运行结果如下:
就是如果重名的话,会先考虑父结构体里面的,要调用子结构体里面的,就是要用结构体名来调用
但是没有重名的就仍然会继承到那个父结构体上面,还是可以像之前一样调用。