Golang
Go语言面向对象编程三大特征 - 继承
11-19 09:02面向对象编程三大特征
Golang仍然有面向对象的继承、封装和多态的特性,只是实现方式和其他OOP语言不一样
继承的介绍
比如有这样的需求:要编写一个学生考试系统,分别有小学、初中、高中等,其中的学生姓名、年龄、分数等字段,是可以共用的
如果按照分类分开写,每个等级都写一遍,代码会出现大量冗余,比如:
//小学生
type Pupil struct {
Name string
Age int
score float64
}
//显示小学生信息
func (p Pupil) ShowInfo() { ... }
//修改小学生成绩
func (p *Pupil) SetScore() { ... }
//大学生
type Graduate struct {
Name string
Age int
score float64
}
//显示大学生信息
func (g Graduate) ShowInfo() { ... }
//修改大学生成绩
func (g *Graduate) SetScore() { ... }
对上面代码的小结:
1、Pupil和Graduate两个结构体的字段和方法几乎一样,代码复用性强
2、出现代码冗余,而且代码不利于维护,同时也不利于功能的扩展
3、解决方法 - 可通过继承方式来解决
快速体验继承:
当多个结构体存在相同的属性(字段)和方法时,可从这些结构体中抽象出结构体,在该结构体中定义这些相同的属性和方法,其它结构体不需要重新定义这些属性和方法,只需要嵌套一个公共的匿名结构体即可
也就是说,在Goalng中,如果一个 struct 嵌套了另一个匿名结构体,那么这个结构体可以直接使用匿名结构体的字段和方法,从而实现了继承特性
首先定义一个Sutdent结构体,其它结构体都嵌入Student匿名结构体

上图的使用方法:

继承带来的便利
1、代码复用性提高了
2、代码的扩展性和维护性提高了
继承的深入讨论
1、结构体可以使用嵌套匿名结构体的所有字段和方法,即:首字母大写或小写的字段、方法,都可以使用

2、匿名结构体字段访问可以简化(赋值和取值,都可以省去匿名结构体的名称)

上面代码的补充说明:
⑴ 访问结构体方法或字段时(上面的 B strcut),编译器会先看结构体自身是否存在这样的字段或方法,如果存在则直接调用
⑵ 如果结构体自身不存在这样的字段或方法(上面的 B strcut),则会去查看结构体中嵌入的匿名结构体,是否存在这样的字段或方法(上面的 A strcut),存在则调用
⑶ 多层嵌套匿名结构体,则依层级查找,若都没有找到要调用的,就会报错
3、当结构体和匿名结构体有相同的字段或者方法时,编译器会采用就近访问原则,优先访问结构体自身的字段和方法(类似重写,但匿名结构体的字段和方法依然存在)
如果希望访问匿名结构体的字段和方法,可以通过匿名结构体名来区分

多层级匿名结构体,体现的更明确

4、结构体嵌入两个(或多个)匿名结构体,如果这些被嵌入的匿名结构体,有相同的字段和方法(同时结构体本身没有同名的字段和方法),在访问时就必须明确指定匿名结构体的名字,否则会报错

正确使用方法:访问时明确指定匿名结构体的名字

5、如果一个 struct 嵌套了一个有名结构体,这种模式就是组合,如果是组合关系,那么在访问组合的结构体的字段或方法时,必须带上结构体的名字

6、嵌套匿名结构体后,也可以在创建结构体变量时,直接指定匿名结构体中各字段的值

7、在嵌套匿名结构体的时候,也可以嵌套这个匿名结构体的指针类型,这时返回的是匿名结构体的地址,效率更高
因为传入的是指针,所以结构体里面变成地址了,直接使用时会返回匿名结构体的地址,因为本身就是把地址给了它,返回两个地址也是顺理成章的事
所以在创建包含指针的匿名结构体时,细节是要给地址,使用时要带取地址符

正确取值方法

8、匿名字段是基本数据类型
继承时,不仅可以把自定的类型做为匿名结构体,还可以把基本数据类型,做为匿名字段放入结构体

需要注意:如果一个结构体有 int 类型的匿名结构体,就不能再有第二个(其它基本数据类型都一样),如果需要多个,则必须给字段指定名字

多重继承
如果一个 struct 嵌套了多个匿名结构体,那么该结构体可以直接访问任意嵌套结构体的字段和方法,从而实现了多重继承

多重继承细节说明
1、如果嵌入的匿名结构体有相同的字段或方法,则访问时必须指明匿名结构体的类型名
2、为了保证代码的间接性,建议尽量不要使用多重继承(Go创造者)