oop三大特性:继承、封装、多态
1.封装介绍
encapsulation就是把抽象出的字段和对字段的操作封装在一起,数据被保护在内部。其它包只有通过被授权的方法,才能对字段进行操作
2.封装的实现步骤
1)将结构字段的首字母小写(类似于private)
2)给结构体所在的包提供一个工厂模式的函数,首字母大写。类似于构造函数
3)提供一个首字母大写的Set方法。用于对属性判断并赋值
func (var structName) Setxxx(paraList) (retList) {
//数据验证的业务逻辑
var.字段 = 参数
}
- 提供一个Get方法,获取值
func (var structName) Getxxx() (retList) {
return var.field
}
go并不强调封装。不像Java每个字段都必须加入get和set
3.在go中,如果struct嵌套了另一个匿名结构体,那么这个结构体可以直接访问匿名结构体的字段和方法。
在匿名结构体中定义公共的字段和方法
type Student struct{
name string
age int
score int
}
func (stu *Student) showInfo() {
fmt.Printf("Name is %v, age is %v score is %v\n",
stu.name, stu.age, stu.score)
}
func (stu *Student) setScore(s int){
stu.score = s
}
type Pupil struct{
Student
}
func (p *Pupil) testing(){
fmt.Println("Pupils are testing...")
}
type Graduate struct{
Student
}
func (g *Graduate) testing(){
fmt.Println("Graduates are testing")
}
func main(){
//对结构体嵌入了匿名结构体
pupil := &Pupil{}
pupil.Student.name = "Tom"
pupil.Student.age = 12
pupil.testing()
pupil.Student.setScore(90)
pupil.Student.showInfo()
g := &Graduate{}
g.Student.name = "Mike"
g.Student.age = 22
g.testing()
g.Student.setScore(80)
g.Student.showInfo()
}
让pupil和graduate结构继承student结构
4.结构体可以使用嵌套匿名结构体(父类)的所有方法和字段,无论大小写
5.对父类的访问可以简化,不用写中间的父类名字
6.如果结构有相同的字段或方法,遵循就近原则,,先看有没有,如果没有就找父类,再没有再向上找
如果强调父类中的成员 要加上结构名
7.如果结构嵌入了多个匿名结构体,且他们含有相同的成员,且结构本身没有这一名字的成员。
此时访问必须加上父类名,否则报错
8.如果结构嵌套了一个有名结构体(struct的一个字段是另一个struct)这种模式就是组合
组合关系就必须加上结构体的名字,不能省略
9.嵌套匿名结构后,在创建实例时,可以直接指定各个匿名结构字段的值
type goods struct{
name string
price int
}
type brand struct{
name string
city string
}
type TV struct{
//也可以嵌套指针
//此时创建实例要加&
goods
brand
}
func main(){
tv := TV{
goods{"tv001", 3999},
brand{"Ahri", "Harbin"},
}
tv2 := TV{
goods{
price: 25554,
name: "tv033",
},
brand{
name: "cw",
city: "tokyo",
},
}
fmt.Println(tv)
fmt.Println(tv2)
}
10.尽量不要多重继承
11.多态主要通过接口实现
接口初体验
type usb interface{
//声明两个没有实现的方法
start()
stop()
}
type phone struct{
}
//让phone实现usb的method
func (p phone) start(){
fmt.Println("Phone starts")
}
func (p phone) stop(){
fmt.Println("phone stops")
}
type camera struct{
}
//camera 也实现usb的方法
func (c camera) start(){
fmt.Println("camera starts")
}
func (c camera) stop(){
fmt.Println("camera stops")
}
type computer struct{
}
//编写一个work方法 接收usb接口类型的变量
//只要实现了usb接口 即usb接口声明的所有方法
func (c computer) work(u usb){
//通过usb接口变量 调用start和stop方法
u.start()
u.stop()
}
func main(){
cpt := computer{}
p := phone{}
cmr := camera{}
cpt.work(p)
cpt.work(cmr)
}
12.interface类型定义一组方法,不需要实现。interface不能包含任何变量。
某个结构要用的时候,再根据具体情况把方法写出来。
接口体现了多态和高内聚、低耦合的思想
实现接口必须实现接口的所有方法、方法的签名必须完全一致
对于结构本身来说,实现了接口的所有方法,结构本身并不知道实现了方法
13.接口不能单独创建实例,但是可以指向一个实现了该接口的类型的变量实例
type a interface{
say()
}
type student struct{
name string
}
func (stu student) say(){
fmt.Println("student say()")
}
func main(){
var stu student // 结构实现了a接口
var aa a = stu
aa.say()
}
14.只要是自定义类型,就可以实现接口。不仅是结构体
一个类型可以实现多个接口
15.一个接口A 可以继承多个别的接口B、C
这时如果要实现A接口,也必须实现BC的全部方法
16.interface默认是一个指针(引用类型)
如果没初始化就输出 会输出nil
17.空接口interface{}没有任何方法。
所有类型都实现了空接口。
如果一个函数参数是空接口,表示可以接收任何类型的任何变量
18.接口不允许有相同的方法名,包括继承而来的
19.interface的经典案例
实现sort.Sort所要求的接口
import (
"fmt"
"sort"
"math/rand"
)
type hero struct{
name string
age int
}
type heroSlice []hero
func (hs heroSlice) Len()int {
return len(hs)
}
//按age从小到大排序
func (hs heroSlice) Less(i, j int) bool{
return hs[i].age < hs[j].age
//return hs[i].name < hs[j].name
}
func (hs heroSlice) Swap(i, j int){
tmp := hs[i]
hs[i] = hs[j]
hs[j] = tmp
// hs[i], hs[j] = hs[j], hs[i]
}
func main(){
//define a slice
var intSlice = []int{2, 5, 6, -1, 4}
//slice是引用类型
sort.Ints(intSlice)
fmt.Println(intSlice)
var heroes heroSlice
for i := 0; i < 10; i++ {
h := hero{
name: fmt.Sprintf("hero-%d", rand.Intn(100)),
age: rand.Intn(5000),
}
heroes = append(heroes, h)
}
//sequence before sort
for _, v := range heroes{
fmt.Println(v)
}
fmt.Println("---------------------")
sort.Sort(heroes)
//sequence after sort
for _, v := range heroes{
fmt.Println(v)
}
}
20。接口一定程度上实现代码解耦
21.接收接口的函数,根据传入实参的不同,就具备不同的功能。体现了多态
22.将空接口类型赋值给其它类型需要使用类型断言
var x interface{}
var a float32 = 1.3
x = a // 空接口接收任意类型
if y, ok := x.(float32); ok {
fmt.Println("convert success")
fmt.Printf("type of y is %T y = %v\n", y, y)
}else{
fmt.Println("convert failed")
}
fmt.Println("go on")
23.断言sample
type usb interface{
//声明两个没有实现的方法
start()
stop()
}
type phone struct{
name string
}
//让phone实现usb的method
func (p phone) start(){
fmt.Println("Phone starts")
}
func (p phone) stop(){
fmt.Println("phone stops")
}
func (p phone) call(){
fmt.Println("calling")
}
type camera struct{
name string
}
//camera 也实现usb的方法
func (c camera) start(){
fmt.Println("camera starts")
}
func (c camera) stop(){
fmt.Println("camera stops")
}
type computer struct{
}
//编写一个work方法 接收usb接口类型的变量
//只要实现了usb接口 即usb接口声明的所有方法
func (c computer) work(u usb){
//通过usb接口变量 调用start和stop方法
u.start()
if p, ok := u.(phone); ok {
p.call()
}
u.stop()
}
func main(){
var usbArr [3]usb
usbArr[0] = phone{"vivo"}
usbArr[1] = phone{"xiaomi"}
usbArr[2] = camera{"canon"}
var c computer
for _, v := range usbArr{
c.work(v)
fmt.Println()
}
}