将一个结构体作为另一个结构体的属性,这种结构体就是结构体嵌套。
结构体嵌套可以模拟面向对象中的两种关系:
聚合关系,一个类作为另一个类的属性
继承关系,一个类作为另一个类的子类
结构体嵌套聚合关系:
type work struct {
typeOfWork string
}
type person struct {
name string
age int
work work
/**
必要的时候,为了避免testClass1的情况出现,可以将work数据改为指针
如:
work *work
而修改赋值的时候,就要用
p.work = &work{
"码农",
}
*/
}
func testClass11(){
p := person{}
p.name = "Yoni"
p.age = 35
w := work{}
w.typeOfWork = "MaNong"
p.work = w
fmt.Println(p)
fmt.Println("----------")
//修改work后再打印p
w.typeOfWork = "CEO"
fmt.Println(p) //修改w对象是没办法修改p对象的
}
func testClass12(){
p := person{}
p.name = "Yoni"
p.age = 35
p.work.typeOfWork = "MaNong"
fmt.Println(p)
fmt.Println("----------")
//修改work后再打印p
p.work.typeOfWork = "CEO"
fmt.Println(p)
}
func testClass13(){
p := person{}
p.name = "Yoni"
p.age = 35
p.work = work{
"码农",
}
fmt.Println(p)
fmt.Println("----------")
//修改work后再打印p
p.work.typeOfWork = "CEO"
fmt.Println(p)
}
结构体嵌套继承关系:
继承是传统面向对象编程中的三大特征之一。
用户描述两个类之间的关系,一个类继承于另一个类。
子类可以有自己的属性和方法,也可以重写父类已有的方法。
子类可以直接访问父类所有的属性和方法。
提升字段:
在结构体中属于匿名结构体的字段称为提升字段,因为他们可以被访问,就好象他们属于拥有匿名结构字段的结构一样。
换句话说,父类中的字段就是提升字段。
继承的意义:
避免重复代码,扩展类的功能。
采用匿名字段的形式就是模拟继承关系。而模拟聚合关系时一定要采用有名字的结构体作为字段。
type person struct {
name string
age int
sex byte
}
type student struct {
person
schoolName string
}
func testClass21() {
p1 := person{"p1", 18, 0}
fmt.Println(p1)
fmt.Println("-----------------")
//实例化方式一:
s1 := student{p1, "第一学校"}
//将详细的键值对打印出来可以用%+v打印
fmt.Printf("%+v \n", s1)
//可以直接访问父结构体的属性
fmt.Printf("姓名:%v,年龄:%v,性别:%v,学校:%v \n",s1.name,s1.age,s1.sex,s1.schoolName)
//实例化方式二:
s2 := student{person{"p2",19,1},"第二学校"}
fmt.Printf("%+v \n", s2)
fmt.Printf("姓名:%v,年龄:%v,性别:%v,学校:%v \n",s2.name,s2.age,s2.sex,s2.schoolName)
//实例化方式三:
s3 := student{person: person{
name:"p3",
age:17,
sex:0,
},
schoolName:"第三学校",
}
fmt.Printf("%+v \n", s3)
fmt.Printf("姓名:%v,年龄:%v,性别:%v,学校:%v \n",s3.name,s3.age,s3.sex,s3.schoolName)
//实例化方式四:
s4 := student{}
s4.name = "p4"
s4.age = 18
s4.sex = 1
s4.schoolName = "第四学校"
fmt.Printf("%+v \n", s4)
fmt.Printf("姓名:%v,年龄:%v,性别:%v,学校:%v \n",s4.name,s4.age,s4.sex,s4.schoolName)
}