Go - 31 Go 面向对象编程思想-抽象/封装/继承
面向对象编程三大特性
Golang任然有面向对象编程的继承,封装和多态的特性,只是实现的方式和其他OOP语言不一样;
如何理解抽象?(研究问题的方法或者编程思想)
我之前定义一个结构体的时候,实际上就是把一类事物的共有的属性(字段)和行为(方法)提取出来,形成一个物理模型(模板),这种研究问题的方法称为抽象;
封装
封装(encapsulation)就是把抽象出的字段和对字段的操作封装在一起,数据被保护在内部,程序的其他包只有通过被授权的操作(方法),才能对字段进行操作。
封装的理解和好处
1.隐藏实现细节;
2.可以对数据进行验证,保证安全合理(Age设置是否合理);
如何体现封装
1.对结构体中的属性进行封装;
2.通过方法,包,实现封装;
封装实现的步骤:
1.将结构体,字段(属性)的首字母小写(不能导出了,其他包不能使用,类似private);
2.给结构体所在包提供一个工厂模式的函数,首字母大写,类似一个构造函数
3.提供一个首字母大写的Set方法(类似其他语言的public),用于对属性判断并赋值
func
4.提供一个首字母大写的Get方法(类似其他语言的public),用于获取属性的值;
特别说明:
在Golang开发中并没有特别强调封装,这点并不像java/python等,Golang本身对面向对象的特性做了简化的;
案例:例如创建一个Person结构体,不能随便查看人的年龄,工资等隐私,并对输入的年龄及逆行合理的验证;
实现:创建一个文件夹(包): model (person.go) main(main.go)
model/person.go
package model
import "fmt"
type person struct {
Name string
age int
sla float64
}
// 结构体首字母小写,需要工厂模式的函数 相当于构造函数
func NewPerson (name string) *person {
return &person{
Name: name,
}
}
// 为了访问age 和sla 我们编写一对Setxxx的方法和Getxxx的方法
func (p *person) SetAge(age int) {
if age > 0 && age < 150 {
p.age = age
}else {
fmt.Println("年龄设置不合法...") // 可以给默认值
}
}
func (p *person) GetAge() int {
return p.age
}
// sla
func (p *person) SetSla(sla float64) {
if sla >= 3000.0 && sla <= 30000 {
p.sla = sla
}else {
fmt.Println("薪水范围不靠谱...")
}
}
func (p *person) GetSla() float64 {
return p.sla
}
调用: main/main.go
package main
import (
"fmt"
. "go_study_file/encapsulation_study/model"
)
func main() {
p := NewPerson("tom")
fmt.Println(*p) // {tom 0 0}
p.SetAge(27)
p.SetSla(17000)
fmt.Println("姓名==",p.Name, "年龄==", p.GetAge(), "薪水===", p.GetSla()) // 姓名== tom 年龄== 27 薪水=== 17000
}
继承
为什么需要继承?
为了防止代码冗余,利于代码维护,功能的扩展---继承的方法(代码复用性高);
继承基本介绍和基本语法:
在结构体中嵌入一个匿名结构体,即实现继承的特性;
当多个结构体存在相同的属性(字段)和方法时,可以从这些结构体中抽象出结构体,在该结构体中定义这些相同的属性和方法。
其他的结构体不需要重新定义这些属性(字段)和方法,只需嵌套一个匿名结构体即可;
也就是说:在Golang中,如果一个struct嵌套了另一个匿名结构体,那么这个结构体可以直接访问匿名结构体的字段和方法,从而实现了继承特性;
继承的深入讨论
1.结构体可以使用嵌套匿名结构体所有的字段和方法,即,首字母大写或者小写的字段/方法都可以使用;
2.匿名结构体字段/方法 访问可以简化;
3.当结构体和匿名结构体有相同的字段或者方法时,编译器采用就近访问原则访问,如希望访问匿名结构体的字段和方法,可以通过匿名结构体名来区分;
4.结构体嵌入两个(或多个)匿名结构体,如两个匿名结构体有相同的字段和方法(同时结构体本身没有同名的字段和方法),在访问时,就必须明确指定匿名结构体名字,否则编译报错。
5.如果一个struct嵌套了一个有名结构体(stu Student),这种模式就是组合,如果是组合关系,那么在访问组合的结构体的字段或方法时,必须带上结构体的名字;
6.嵌套匿名结构体后,也可以在创建结构体变量(实例)时,直接指定各个匿名结构体字段的值。
7注意:
1.如果一个结构体有int类型的匿名字段,就不能有第二个;
2.如果需要有多个int的字段,则必须给int字段指定名字;
3.
多重继承-说明
如果一个struct嵌套了多个匿名结构体,那么该结构体可以直接访问嵌套的匿名结构体的字段和方法,从而实现了多重继承。
细节注意:
1.如嵌入的匿名结构体有相同的字段或者方法名,则在访问时,需要通过匿名结构体名来区分。
2.为了保证代码的简洁性,建议大家尽量不使用多重继承;