面向对象
封装性
- 封装性就是隐藏实现细节,仅对外公开接口类是数据与功能的封装,数据就是成员变量,功能就是方法
- 为什么要封装?
- 不封装的缺点:当一个类把自己的成员变量暴露给外部的时候,那么该类就失去对该成员变量的管理权,别人可以任意的修改你的成员变量
- 封装就是将数据隐藏起来,只能用此类的方法才可以读取或者设置数据,不可被外部任意修改是面向对象设计本质(将变化隔离)。这样降低了数据被误用的可能 (提高安全性和灵活性)封装原则
- 将不需要对外提供的内容都隐藏起来,把属性都隐藏,提供公共的方法对其访问
继承性
- Go 语言认为虽然继承能够提升代码的复用性, 但是会让代码腐烂, 并增加代码的复杂度.
- 所以 go 语言坚持了〃组合优于继承〃的原则, Go 语言中所谓的继承其实是利用组合实现的(匿名结构体属性)
package main
import "fmt"
type Person struct {
name string
age int
}
type Student struct {
Person // 学生继承了人的特性
score int
}
type Teacher struct {
Person // 所谓的组合
Title string
}
func main() {
s := Student{Person{"lnj", 18}, 99}
//fmt.Println(s.Person.name)
fmt.Println(s.name) // 两种方式都能访问
//fmt.Println(s.Person.age)
fmt.Println(s.age) // 两种方式都能访问
fmt.Println(s.score)
}
- 在 Go 语言中子类不仅仅能够继承父类的属性, 还能够继承父类的方法
package main
import "fmt"
type Person struct {
name string
age int
}
// 父类方法
func (p Person) say() {
fmt.Println("name is ", p.name, "age is ", p.age)
}
type Student struct {
Person
score float32
}
func main() {
stu := Student{Person{"zs", 18}, 59.9}
stu.say()
}
- 如果子类有和父类同名的方法, 那么我们称之为方法重写
package main
import "fmt"
type Person struct {
name string
age int
}
// 父类方法
func (p Person) say() {
fmt.Println("name is ", p.name, "age is ", p.age)
}
type Student struct {
Person
score float32
}
// 子类方法
func (s Student) say() {
fmt.Println("name is ", s.name, "age is ", s.age, "score is ", s.score)
}
func main() {
stu := Student{Person{"zs", 18}, 59.9}
// 和属性一样, 访问时采用就近原则
stu.say()
// 和属性一样, 方法同名时可以通过指定父类名称的方式, 访问父类方法
stu.Person.say()
}
- 无论是属性继承还是方法继承, 都只能子类访问父类, 不能父类访问子类
多态性
- 多态的主要好处就是简化了编程接口。它允许在类和类之间重用一些习惯性的命名,而不用为每一个新的方法命名一个新名字。这样,编程接口就是一些抽象的行为的集合,从而和实现接口的类 区分开来。
- 多态也使得代码可以分散在不同的对象中而不用试图在一个方法中考虑到所有可能的对象。这样使得您的代码扩展性和复用性更好一些。当一个新的情景出现时,您无须对现有的代码进行改动,而只需要增加一个新的类和新的同名方法。
package main
import "fmt"
// 1.定义接口
type Animal interface {
Eat()
}
type Dog struct {
name string
age int
}
// 2.实现接口方法
func (d Dog) Eat() {
fmt.Println(d.name, "正在吃东西")
}
type Cat struct {
name string
age int
}
// 2.实现接口方法
func (c Cat) Eat() {
fmt.Println(c.name, "正在吃东西")
}
// 3.对象特有方法
func (c Cat) Special() {
fmt.Println(c.name, "特有方法")
}
func main() {
// 1.利用接口类型保存实现了所有接口方法的对象
var a Animal
a = Dog{"旺财", 18}
// 2.利用接口类型调用对象中实现的方法
a.Eat()
a = Cat{"喵喵", 18}
a.Eat()
// 3.利用接口类型调用对象特有的方法
//a.Special() // 接口类型只能调用接口中声明的方法, 不能调用对象特有方法
if cat, ok := a.(Cat); ok {
cat.Special() // 只有对象本身才能调用对象的特有方法
}
}
旺财 正在吃东西
喵喵 正在吃东西
喵喵 特有方法