GO只支持封装,不支持继承,那么如果我们想要对其他包上的一些类型进行扩展,比如说在原有结构体上加上一些自己的东西,C++中可以用继承实现,但是GO没有,所以GO引入了组合,用组合来实现继承的功能,同样起到代码复用的效果。
如果我们想在本包中使用别的包中的类型,但又不想使用它的名字,使用别名就可以搞定。
如果想要在本包中使用别的包中的类型,同时想在此基础上,添加一些功能和内容,就可以使用组合,下面来讲组合。
这边为了方便演示,就在同一个包中演示了。
//父结构体,表示人
type person struct{
name string
age int
}
//子结构体,继承父类的属性,同时还有别的属性
type student struct {
person //这部分只放一个person,那么这里就是一个匿名变量
class string
sno string
}
func main() {
a := student{person:person{name:"pigff",age:21},class:"计本154",sno:"12345678"}
fmt.Println(a.name)
}
输出结果
pigff
如上代码,定义了一个person结构体表示人,它有字段name和age,再定义了一个student结构体,它里面有一个匿名字段,该字段类型是person(该字段名默认和类型名一样,这一点可以在main函数的赋值语句看到),还有自己的字段class和sno。这样的结构体类型就起到了继承的效果,student结构体继承了person结构体的所有字段name和age,因为我们将该字段定义成了匿名字段,因此,我们可以直接打印 (a.name),直接访问到person结构体中的字段
如果不定义成匿名字段会怎样,来上代码
//父结构体,表示人
type person struct{
name string
age int
}
//子结构体,继承父类的属性,同时还有别的属性
type student struct {
basic person //这部分只放一个person,那么这里就是一个匿名变量
class string
sno string
}
func main() {
a := student{basic:person{name:"pigff",age:21},class:"计本154",sno:"12345678"}
fmt.Println(a.name)
}
我们在student结构体中定义了一个person类型的变量的basic,因此我们下面在赋值的时候也是用的basic。但是这样的程序会出错
.\main.go:21:15: a.name undefined (type student has no field or method name)
a中没有字段名叫name,也就是说,我们不能直接访问我们继承下来的父结构体的字段。
所以,如果想要访问原有类型的字段,那么就需要在结构体中将该类型定义成匿名字段(通常都是定义成匿名字段的)。
这两个结构体不是继承的关系,是组合,但是它起到了继承的效果,也有继承最关键的作用——代码复用。
另外还要说一点:如果要组合的原类型很大,那么在组合类型中最好将该字段定义成指针类型,这样可以节省空间。