抽象
抽象是一种编程思维方式,是从多个事物中提取共性
例:产品经理和程序员都有工作的方法,但是工作内容不同,可以把工作抽象出来定义为一个方法,具体细节由调用者补充
银行存取款案例:
- 账号结构体
- 取款方法(账户一天最多2w)
- 存款方法(每次最多1w)
- 查余额分期
package mainimport "fmt"// 账户信息
type Account struct {AccountNumber intBalance float64Password int
}// 校验密码
func (password Account) JudgePassword(password int) {var password inti := 3fmt.Println("请输入密码")fmt.Scan(&password)if password == account.password {fmt.Println("抱歉,密码输入错误,今日剩余"+(i--)+"次,超出3次后将锁定银行卡")return}
}// 查询余额
func (account Account) QueryBalance(passwprd int) {fmt.Println("余额为:", account.Balance)
}// 存款
func (account *Account) Query(passwprd int) {var money intfmt.Println("请输入要存的金额")fmt.Scan(&money)fmt.Println("存款成功")fmt.Println("当前余额为:", account.Balance)
}// 取款
func (account *Account) Query() {var money intfmt.Println("请输入要存的金额")fmt.Scan(&money)if account.Balance-(float64(money)) > 0 {fmt.Println("余额不足")} else {account.Balance -= (account.Balance)moneyfmt.Println("取款成功")fmt.Println("当前余额为:", account.Balance)}fmt.Println("存款成功")fmt.Println("当前余额为:", account.Balance)
}
封装:
封装是指将结构体的某些信息隐藏在内部,不允许外部程序直接访问,而是授权方法来对隐藏的信息进行操作和访问。结构体名称小写就是封装,仅本包下可访问,大写为公开,所有包可访问。
大写的可以调用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OcUK3kj9-1671674799005)(/Users/itzhuzhu/Library/Application Support/typora-user-images/image-20221021160333106.png)]
使用函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DQhLYjMO-1671674799007)(/Users/itzhuzhu/Library/Application Support/typora-user-images/image-20221021160952307.png)]
如果成员是小写的,就通过getset方式(类似)解决
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lJbRczkn-1671674799007)(/Users/itzhuzhu/Library/Application Support/typora-user-images/image-20221021161259823.png)]
继承
继承是一种类和类之间的关系,描述的是子类从父类获取成员信息的现象。
在Go中没有类似其它语言的继承语法,而是使用匿名字段实现继承的概念
父类和子类中有重复的变量、方法时,子类优先使用自己的,如果需要使用父类的需要使用
子类.父类.变量/方法
调用只要在子类结构体内写上父类名称即可实现继承,如果一个struct嵌套了另一个匿名结构体,那么这个结构体可以直接访问结构体的字段和方法,从而实现了继承特性。
就近原则:
在子类中访问成员,采用的是就近原则,先看自己有没有,没有就找爸爸要,优先级如下
子类局部范围 -> 子类成员范围找 -> 父类成员范围找 -> 如果都没有就去父亲的父亲找
// 父类
type Person struct {name stringage int
}// 子类-学生
type Student struct {Person // 匿名字段,只有类型,没有成员名
}// 子类-老师
type Teacher struct {Person
}func main() {// 具体继承父类哪些成员,可自定义,可以只继承部分s := Student{Person{"itzhuzhu",23}}t := Teacher{Person{name: "itzhuzhu",}}//格式2t2 := Teacher{Person: Person{name: "itzhuzhu",}}// 获取成员值// 获取逻辑:先判断子类中是否有name这个成员,如果没有就会向父类中查找,如果还没有就报错(就近原则,优先使用自己的)fmt.Println(t.name)fmt.Println(t.Person.name)// 修改成员的值,不会影响到其它子类中的成员值fmt.Println("修改前:", t.age,s.age)t.age = 999fmt.Println("修改后:", t.age,s.age)fmt.Println(s)fmt.Println(t)fmt.Println(t2)
}
无论父类中的字段、方法是否大小写,子类都可以访问
type Person struct {Name stringage 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 stringage int
}type Student struct {*Person
}
多重继承:
多重继承后,子类可以直接使用.
父类的父类成员
func main() {stu := Student{score: 100}stu.id = 001stu.name = "itzhuzhu"stu.age = 24fmt.Println(stu.score)fmt.Println(stu.Person.name)fmt.Println(stu.Person.age)fmt.Println(stu.Person.Object.id)
}type Object struct {id int
}
type Person struct {Objectname stringage int
}type Student struct {Personscore float64
}type Teacher struct {Personsalary float64
}