面向对象:
把数据和处理数据的方法组成对象,把相同行为的对象归纳为类,通过类的封装隐藏内部细节,通过继承实现类的转化,通过多态实现基于对象类型的动态分派,面向对象实现思路就是先把事物抽象成对象。
面向对象三大特征:封装、继承、多态
面向对象实现思路:
人骑车,先定义两个对象,分别是人、车,再为每个对象添加方法
人:开锁、骑车、停车
车:启动、行驶、锁车
然后依次执行开锁 > 启动 > 骑车 > 行驶 > 停车 > 锁车
封装:人和车都被抽象为对象
继承:如果是小明骑车,让小明继承人就可以获取所有骑车方法
多态:小明将开锁方法重写为指纹解锁,这就是多态,一个事物有多种形态
抽象
抽象是一种编程思维方式,是从多个事物中提取共性
学生和老师都有吃饭、说话、走路的属性,这就是共同属性
type Student struct {
eat, speak, walk string
}
type Teacher struct {
eat, speak, walk string
}
抽象:把共同的属性抽取为Person,学生、老师都去继承即可
type Person struct {
eat, speak, walk string
}
type Student struct {
Person
}
type Teacher struct {
Person
}
封装:
封装是将事物封装成对象,结构体的某些信息隐藏在内部,不允许外部程序直接访问,而是授权方法来对隐藏的信息进行操作和访问。结构体名称小写就是封装,仅本包下可访问,大写为公开,所有包可访问。
小写的结构体、成员、函数均无法在包外调用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0OODufog-1676805800672)(/Users/itzhuzhu/Library/Application Support/typora-user-images/image-20230219190125699.png)]
可以通过类似Get、Set方式解决,使用方法关联结构体
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nDBUdGLO-1676805800673)(/Users/itzhuzhu/Library/Application Support/typora-user-images/image-20230219191353574.png)]
继承
继承是一种类和类之间的关系,描述的是子类从父类获取成员信息的现象。
在Go中没有类似其它语言的继承语法,而是使用匿名字段实现继承的概念
父类和子类中有重复的变量、方法时,子类优先使用自己的,如果需要使用父类的需要使用
子类.父类.变量/方法
调用如果一个struct嵌套了另一个匿名结构体,那么这个结构体可以直接访问结构体的字段和方法,从而实现了继承特性。
就近原则:
在子类中访问成员,采用的是就近原则,先看自己有没有,没有就找爸爸要,优先级如下
子类局部范围 -> 子类成员范围找 -> 父类成员范围找 -> 如果都没有就去父亲的父亲找
// 父类
type Person struct {
name string
age int
}
// 子类-学生
type Student struct {
Person // 匿名字段就是继承
}
// 子类-老师
type Teacher struct {
Person
}
func main() {
// 具体继承父类哪些成员,可自定义,可以只继承部分
s := Student{Person{"itzhuzhu", 23}}
t := Teacher{Person{
name: "itzhuzhu",
}}
// 获取成员值
// 获取逻辑:先判断子类中是否有name这个成员,如果没有就会向父类中查找,如果还没有就报错(就近原则,优先使用自己的)
fmt.Println(t.name)
fmt.Println(t.Person.name)
// 修改成员的值,不会影响到其它子类中的成员值
fmt.Println("修改前:", t.age, s.age)
t.age = 999
fmt.Println("修改后:", t.age, s.age)
}
无论父类中的字段、方法是否大小写,子类都可以访问
type Person struct {
Name string
age int
}
func (p *Person) personMethod() {
fmt.Println("我是Person的方法")
}
type Student struct {
Person
}
func main() {
s := Student{Person{Name: "韩信", age: 99}}
s.personMethod()
fmt.Println(s)
}
匿名字段加上*就是指针类型
type Person struct {
name string
age int
}
type Student struct {
*Person // 匿名字段就是继承
}
type Teacher struct {
*Person
}
func main() {
s := Student{&Person{"itzhuzhu", 23}}
t := Teacher{&Person{
name: "itzhuzhu",
}}
fmt.Println(s, t)
}
多重继承:
多重继承后,子类可以直接使用.
父类的父类成员
type Object struct {
id int
}
type Person struct {
Object
name string
age int
}
type Student struct {
Person
score float64
}
func main() {
stu := Student{score: 100}
// id是父类的父类成员
stu.id = 001
stu.name = "itzhuzhu"
stu.age = 24
fmt.Println(stu.score)
fmt.Println(stu.name) // 等同于stu.Person.name
fmt.Println(stu.age)
fmt.Println(stu.id)
}