一、为什么需要继承
1、继承基本介绍
1)继承可以解决代码复用,让我们的编程更加靠近人类思维。
2)当多个结构体存在相同的属性(字段)和方法时,可以从这些结构体中抽象出结构体(比如刚才的Student),在该结构体中定义这些相同的属性和方法。
3)其它的结构体不需要重新定义这些属性(字段)和方法,只需嵌套一个Student匿名结构体即可。
2、示意图
也就是说:在Golang中,如果一个struct嵌套了另一个匿名结构体,那么这个结构体可以直接访问匿名结构体的字段和方法,从而实现了继承特性。
二、如何使用继承
1、继承基本语法
在GO中通过嵌套匿名结构体实现继承。
type Goods struct {
Name string
Price int
}
type Book struct {
Goods //这里就是嵌套匿名结构体Goods
Writer string
}
三、快速入门案例
//继承快速入门案例
type student struct {
name string
age int
score float64
}
func (s *student) setGrade(score float64) {
s.score=score
}
func (s *student) showInfor() {
fmt.Printf("学生信息如下:姓名:%s 年龄:%d 分数:%f \n",
s.name,s.age,s.score)
}
type collegeStudent struct{
student
writeThesis bool
}
type middleStudent struct{
student
college bool
}
type middleStudentPoint struct{
*student
college bool
}
func (c *collegeStudent) graduation() {
res := "未毕业"
if c.writeThesis {
res = "已毕业"
}
fmt.Printf("毕业信息如下:姓名:%s 年龄:%d 分数:%f 是否毕业: %s\n",
c.name,c.age,c.score,res)
}
func (p *primaryStudent) showInfor() {
fmt.Printf("学生信息如下:姓名:%s 年龄:%d 分数:%f \n",
p.name,p.age,p.score)
}
func ExtendDemo() {
// 匿名结构体字段访问可以简化
/*继承结构体的声明方式1*/
var college collegeStudent
college.score = 70.5
college.name = "张三"
college.age = 23
college.showInfor()
college.student.setGrade(59.1)
college.showInfor()
college.writeThesis = true
college.graduation()
/*继承结构体(匿名结构体)的声明方式2*/
middle := middleStudent{
student : student{
name : "王辉",
age : 44,
score : 50,
},
college :true,
}
/*继承结构体的声明方式3*/
middle1 := middleStudent{
student{ "王辉",44,90,},true,
}
middle.showInfor()
middle1.showInfor()
/*指针*/
/*继承结构体的声明方式4*/
middlep :=middleStudentPoint{&student{ "刘亦菲",44,90,},true,}
/*继承结构体的声明方式5*/
middlep1 :=middleStudentPoint{
student : &student{
name : "小龙女",
age : 44,
score : 50,
},
college :true,}
middlep.showInfor()
middlep1.showInfor()
}
四、继承给编程带来的便利
1、代码的复用性提高了
2、代码的扩展性和维护性提高了
五、继承使用细节和注意事项
1、结构体可以使用嵌套匿名结构体所有的字段和方法,即:首字母大写或者小写的字段、方法,都可以使用。
type student struct {
name string
age int
score float64
}
func (s *student) setGrade(score float64) {
s.score=score
}
func (s *student) showInfor() {
fmt.Printf("学生信息如下:姓名:%s 年龄:%d 分数:%f \n",
s.name,s.age,s.score)
}
type collegeStudent struct{
student
writeThesis bool
}
func ExtendDemo() {
var college collegeStudent
college.score = 70.5
college.name = "张三"
college.age = 23
college.showInfor()
college.student.setGrade(59.1)
college.showInfor()
}
2、匿名结构体字段访问可以简化。
college.score = 70.5
college.student.name = "张三"
使用简化的方法区访问字段或者方法的流程
(1) 先到本身结构体去找字段或者方法,如果找到,就直接调用
(2) 如果找不到,就到匿名结构体去找,如果找到就调用,否则继续向上找。
(3) 如果一直找不到,则报错
3、当结构体和匿名结构体有相同的字段或者方法时,编译器采用就近访问原则访问,如希望访问匿名结构体的字段和方法,可以通过匿名结构体名来区分【案例演示】
/*
当结构体和匿名结构体有相同的字段或者方法时,编译器采用就近访问原则访问,
如希望访问匿名结构体的字段和方法,可以通过匿名结构体名来区分
*/
type primaryStudent struct{
student
age int
}
func ExtendDemo2() {
primary := primaryStudent{
student : student{
name : "小龙",
age : 9,
score : 50,
},
age :13,
}
primary.student.showInfor()
primary.showInfor()
}
4、结构体嵌入两个(或多个)匿名结构体,如两个匿名结构体有相同的字段和方法(同时结构体本身没有同名的字段和方法),在访问时,就必须明确指定匿名结构体名字,否则编译报错。【案例演示】
/*
结构体嵌入两个(或多个)匿名结构体,如两个匿名结构体有相同的字段和方法(同时结构体本身没有同名的字段和方法),
在访问时,就必须明确指定匿名结构体名字,否则编译报错。
*/
type person struct {
name string
age int
score float64
}
type user struct {
person
student
score float64
}
// 如嵌入的匿名结构体有相同的字段名或者方法名,则在访问时,需要通过匿名结构体类型名来区分。
func ExtendDemo3() {
var root user
// root.age = 23
root.person.age = 23
root.score = 23
root.person.score = 23
root.student.score = 23
}
5、如果一个struct嵌套了一个有名结构体,这种模式就是组合,如果是组合关系,那么在访问组合的结构体的字段或方法时,必须带上结构体的名字。【案例参考4】
6、嵌套匿名结构体后,也可以在创建结构体变量(实例)时,直接指定各个匿名结构体字段的值。
六、多重继承
1、多重继承说明
如一个struct嵌套了多个匿名结构体,那么该结构体可以直接访问嵌套的匿名结构体的字段和方法,从而实现了多重继承。
2、案例演示
通过一个案例来说明多重继承使用。
type Good struct{
Name string
Price float64
}
type Band struct{
Name string
Address string
}
type Test struct{
Band
Good
}
func ExtendDemo5() {
var t Test
t.Band.Name = "zsff"
t.Good.Name = "qrqf"
}
3、多重继承细节说明
1) 如嵌入的匿名结构体有相同的字段名或者方法名,则在访问时,需要通过匿名结构体类型名来区分。
2) 为了保证代码的简洁性,建议大家尽量不使用多重继承