面对对象介绍
/*
面向对象的三大特性或四大特性:
封装: 化繁为简,将业务相近的变量,函数封装为结构体(类),减少直接管理的成员数,便于做大规模开发。
继承:将公共的部分提取到父类,减少重复代码,继承另外便于扩展和覆写修改类方法
多态:1.一个父类,有多种不同的具体子类形态,2.共性:通过父类方法去调度子类实例.3.个性:不同子类对父类方法的具体实现各不相同。
------
抽象:父类接口只定义方法,不做具体实现(比如战士接口,抽象方法1:进攻,抽象方法2:防守)
*/
1 封装
封装,值传递,引用传递
1 package main
2
3 import "fmt"
4
5 //定义一个类型,是个人,是一个结构体
6 type Person struct {
7 //封装结构体的【属性】
8 name string
9 age int
10 sex bool
11 hobby []string
12 }
13
14 /*
15 封装结构体方法
16 -无论方法的主语定义为值类型还是指针类型,对象值和对象指针都能够正常访问。
17 -通常会将主语定义为指针类型,毕竟小红的副本吃了饭,肉不会长到小红本人身上去。所以需要访问*Pesion
18 */
19 //方法:将定义的人,传递给Eat吃,具体哪个人吃.
20 func (p *Person) Eat() {
21 fmt.Printf("%s爱吃..
", p.name)
22
23 }
24
25 func (p *Person) Drink() {
26 fmt.Printf("%s爱喝..
", p.name)
27
28 }
29
30 /* 以上为一个结构体 */
31
32 //创建对象,并通过对象的值去访问对象的属性和方法。
33 func main() {
34
35 //创建空白的对象/实例
36 ren := Person{}
37
38 //设置其属性
39 ren.name = "小红"
40
41 //调用其方法
42 ren.Eat()
43 ren.Drink()
44 }
创新对象时,指定属性
1 package main
2
3 import "fmt"
4
5 //定义一个类型,是个人,是一个结构体
6 type Person struct {
7 //封装结构体的【属性】
8 name string
9 age int
10 sex bool
11 hobby []string
12 }
13
14 func (p *Person) Eat() {
15 fmt.Printf("%s爱吃..
", p.name)
16
17 }
18
19 func (p *Person) Drink() {
20 fmt.Printf("%s爱喝..
", p.name)
21
22 }
23
24 func (p *Person) jieshao() {
25 fmt.Printf("我是%s,今年%d岁了
", p.name, p.age)
26 }
27
28 func main() {
29
30 //方式1 : 给值定的属性赋值 创新对象时,赋予对象一些属性。
31 //ren := &Person{name: "小红", age: 18}
32
33 //方式2: 按顺序给所有属性赋值
34 //ren :=&Person{"小红",18,true,[]string{"aa"}}
35
36 ren.Eat()
37 ren.Drink()
38 ren.jieshao()
39 }
值传递和引用传递区别
/*
值传递 传递的是副本.
引用传递 传递的是真身。
*/
1 package main
2
3 import "fmt"
4
5
6
7
8 type Person struct {
9 name string
10 age int
11 sex bool
12 hobby []string
13 }
14
15
16
17
18 func (p *Person) Eat() {
19 fmt.Printf("%s爱吃..
", p.name)
20
21 }
22
23
24
25
26 //引用传递
27 func zhi(p Person) {
28 p.Eat()
29 p.age -= 1
30 }
31
32
33
34
35
36 //值传递
37 func zhizhen(p *Person) {
38 p.Eat()
39 p.age -= 1
40
41 }
42
43
44
45
46 func main() {
47
48
49 ren := Person{name: "小红", age: 18}
50
51
52
53 //要求传递数值 必须传递数值
54 //zhi(ren)
55
56
57
58
59 //要求传递指针必须传递指针(指针/地址/引用传递)
60 //zhizhen(&ren)
61
62
63
64
65 //值传递 传递的是副本,引用传递传递的才是真身.
66 // for i:=1;i<7;i++{
67 // zhi(ren) //这里是数值传递
68 // }
69 //fmt.Println(ren.age) //18 数值没有变化,因为用的是分身,不是真身。
70
71
72
73
74 //使用真身
75 for i:=1;i<7;i++{
76 zhizhen(&ren) //使用真身地址
77 }
78 fmt.Println(ren.age) //12
79
80
81 }
2 继承性
1 package main
2
3 import "fmt"
4
5 //会吃
6 func (p *person) Eat() {
7 fmt.Printf("%s爱吃..
", p.name)
8
9 }
10
11 //会喝
12 func (p *person) Drink() {
13 fmt.Printf("%s爱吃..
", p.name)
14
15 }
16
17 //会爱爱
18 func (p *person) Love() {
19 fmt.Printf("%s爱美女..
", p.name)
20
21 }
22
23 //封装一个人类
24 type person struct {
25 name string
26 age int
27 sex bool
28 hobby []string
29 }
30
31 //堆代码的
32 type coder struct {
33 //持有一个父类的声明,也就是继承了Persion
34 person
35
36 //会的语言
37 langs []string
38 }
39
40 //堆代码的特有方法
41 func (c *coder) Code() {
42 fmt.Printf("%s会%v正在怼代码", c.name, c.langs)
43 }
44
45 //封装一个司机类
46 type driver struct {
47 person
48
49 jiazhaoID string
50 isDriving bool
51 }
52
53 //司机的特有方法
54 func (d *driver) drive() {
55 fmt.Printf("%s一言不合就开车", d.name)
56 }
57
58 //覆写父类方法 司机的特有方法
59 func (d *driver) Drink() {
60 if !d.isDriving {
61 fmt.Printf("%s爱喝酒
", d.name)
62 } else {
63 fmt.Println("fuckoff,司机一滴酒亲人泪两行")
64 }
65 }
66
67 func main() {
68
69 ////撸代码的使用
70 //c := new(coder)
71 //c.name = "小红"
72 //c.langs=[]string{"go","汉语"}
73 //c.Drink()
74 //c.Code()
75
76 /*
77 小红爱吃..
78 小红会[go 汉语]正在怼代码
79 */
80
81 //开车司机的使用
82 aa := new(driver)
83 aa.name = "小张"
84 aa.Eat()
85
86 aa.jiazhaoID = "京B6666"
87 //aa.isDriving=false //小张爱喝酒
88 aa.isDriving = true //fuckoff,司机一滴酒亲人泪两行
89
90 aa.Drink()
91
92 }
借书案例
封装书的结构体 属性有: 书名,价格,作者
封装读者类 属性有: ReaderID,押金余额,方法有:借书,还书,交罚款.
封装学生类 继承读者类,扩展专业属性和学习方法.
封装老师类 继承读者类,扩展课程属性和教学方法,修改交罚款方法(老师不用交罚款)
1 package main
2
3 import "fmt"
4
5 //封装书类
6 type Book struct {
7 Name string
8 Price float64
9 Author string
10 Borrowable bool
11 }
12
13 //读者类
14 type Reader struct {
15 ReaderID string //读者id
16 Balance float64 //押金余额
17 }
18
19 //借书方法
20 func (r *Reader) BorrowBook(b *Book) {
21 if b.Borrowable {
22 b.Borrowable = false
23 fmt.Printf("读者%s借阅了%s
", r.ReaderID, b.Name)
24 } else {
25 fmt.Printf("读者%s借阅失败,%s已被借出..
", r.ReaderID, b.Name)
26 }
27 }
28
29 //还书方法
30 func (r *Reader) ReturnBook(b *Book) {
31 fmt.Printf("读者%s归还了%s
", r.ReaderID, b.Name)
32 }
33
34 //交罚款方法
35 func (r *Reader) PayPenalty(amount float64) {
36 //罚钱
37 r.Balance -= amount
38 fmt.Printf("读者%s缴纳了%.2f元,余额是%.2f
", r.ReaderID, amount, r.Balance)
39
40 }
41
42 //覆写交罚金方法.老师不存在交罚金
43 func (t *Teacher) PayPenalty(amount float64) {
44 fmt.Printf("读者%s缴纳了%.2f元,余额是%.2f
", t.ReaderID, amount, t.Balance)
45
46 }
47
48 //封装学生模型 ,继承读者类
49 type Student struct {
50 Reader //继承Reader
51
52 Name string //姓名
53 Major string //学生特有属性
54 }
55
56 //学生独有的方法
57 func (s *Student) Study() {
58 fmt.Println("%s正在学习..", s.Name)
59 }
60
61 //封装老师模型 ,继承读者类
62 type Teacher struct {
63 Reader //继承Reader
64
65 Name string //姓名
66 Curse string //老师特有属性
67 }
68
69 //老师独有的方法
70 func (t *Teacher) Teach() {
71 fmt.Println("%s正在教授%s..", t.Name, t.Curse)
72 }
73
74 func main() {
75
76 //创建书
77 //赋值方式1 给对象赋值
78 b1 := Book{}
79 b1.Name = "小红书"
80 b1.Author = "小红"
81 b1.Price = 50
82 b1.Borrowable = true
83
84 //赋值方式2 给对象赋值
85 b2 := Book{"小黄书", 100, "小黄", true}
86 //赋值方式3 给对象赋值
87 b3 := Book{Name: "小蓝书", Price: 100, Borrowable: true}
88
89 //赋值方式4 给指针赋值
90 b4 := new(Book)
91 b4.Name = "小黑书"
92 b4.Author = "小黑"
93 b4.Price = 500
94 b4.Borrowable = true
95
96 //fmt.Println(b1,b2,b3,b4)
97
98 //创建一个Reader
99 r1 := Reader{"001", 100}
100
101 //创建学生
102 s1 := Student{r1, "小红", "python"}
103 //fmt.Printf("%v
",s1) //正常输出
104 //fmt.Printf("%+v
",s1) //详细输出
105 //fmt.Printf("%#v
",s1) //超详细输出
106
107 //创建老师
108 t1 := Teacher{Reader{"001", 0}, "李老师", "go"}
109 fmt.Printf("%+v
", t1) //详细输出
110
111 t1.Teach() //老师教学
112 s1.Study() //学生学习
113
114 t1.BorrowBook(&b1) //老师借书
115 t1.BorrowBook(&b2) //老师借书
116 s1.BorrowBook(&b3) //学生借书
117 s1.BorrowBook(b4) //学生借书
118 s1.BorrowBook(&b3) //学生借书
119
120 t1.ReturnBook(&b1) //老师还书
121 t1.ReturnBook(&b2) //老师还书
122 s1.ReturnBook(&b3) //学生还书
123 s1.ReturnBook(b4) //学生还书
124 s1.ReturnBook(&b3) //学生还书
125
126 s1.PayPenalty(5) //交罚款
127
128 }
129
130 /*
131 读者001借阅了小红书
132 读者001借阅了小黄书
133 读者001借阅了小蓝书
134 读者001借阅了小黑书
135 读者001借阅失败,小蓝书已被借出..
136 读者001归还了小红书
137 读者001归还了小黄书
138 读者001归还了小蓝书
139 读者001归还了小黑书
140 读者001归还了小蓝书
141 读者001缴纳了5.00元,余额是95.00
142 */
3 接口和多态
案例
1 /*
2 变量----属性
3 函数---方法
4 接口: 只有方法的定义,没有实现. 也就是全部是抽象方法.
5 实现接口: 结构体实现接口的全部抽象方法.
6 多态: 一个父类/接口有不同的子类实现,本例中【劳动者接口】的具体实现有【程序员】【产品经理】【老板】
7 共性: 【程序员】【产品经理】【老板】都会劳动和休息
8 个性: 【程序员】【产品经理】【老板】的劳动和休息方式各不相同.
9
10 */
11
12 package main
13
14 import (
15 "fmt"
16 "math/rand"
17 "time"
18 )
19
20 func main() {
21 //创建Worker组成的切片
22 workers := make([]Worker, 0)
23
24 //添加有问题 cannot use Coder literal (type *Coder) as type Worker in append:
25 workers = append(workers, &Coder{"撸代码"})
26 workers = append(workers, &ProductManager{"拍脑门"})
27 workers = append(workers, &Boss{"吹牛逼"})
28
29 //随机生成今天星期几
30 r := rand.New(rand.NewSource(time.Now().UnixNano()))
31 weekday := r.Intn(7)
32 fmt.Printf("今天是星期%d
", weekday)
33
34 //工作日全体工作
35 if weekday > 0 && weekday < 6 {
36 for _, worker := range workers {
37 worker.Work(8)
38 }
39 } else {
40 //全体休息
41 for _, worker := range workers {
42 worker.Rest()
43 }
44 }
45
46 }
47
48 //劳动者父类接口
49 //内含俩个抽象方法:工作,休息.
50 type Worker interface {
51 //每天工作多少小时,产出何种产品
52 Work(hour int) (product string) //定义了一个方法没有做实现,就是接口
53
54 //休息
55 Rest() //定义了一个方法没有做实现,就是接口
56 }
57
58 //程序员
59 type Coder struct {
60 skill string
61 }
62
63 //程序员指针实现Worker接口,因为这里写的WOrk和Rest方法写的和上面定义的一致,所以就可以说 程序员实现了工人这个接口。
64 func (c *Coder) Work(hour int) (product string) {
65 fmt.Printf("码农一天工作%d小时
", hour)
66 fmt.Printf("码农正在%s
", c.skill)
67 return "BUG"
68 }
69
70 //程序员休息的方法
71 func (c *Coder) Rest() {
72 fmt.Println("休息是什么?")
73 }
74
75 //程序员特有方法
76 func (c *Coder) WorkHome() {
77 fmt.Println("程序员在家工作")
78 }
79
80 //产品经理
81 type ProductManager struct {
82 skill string
83 }
84
85 //ProductManager指针实现worker接口
86 func (pm *ProductManager) Work(hour int) (product string) {
87 fmt.Printf("产品一天工作%d小时
", hour)
88 fmt.Printf("产品正在%s
", pm.skill)
89 return "无逻辑的需求"
90
91 }
92
93 func (pm *ProductManager) Rest() {
94 fmt.Println("看程序员卤代码")
95 }
96
97 //老板
98 type Boss struct {
99 skill string
100 }
101
102 //Boss指针实现Worker接口
103 func (b *Boss) Work(hour int) (product string) {
104 fmt.Printf("老板一天工作%d小时
", hour)
105 fmt.Printf("老板正在%s
", b.skill)
106 return "梦想"
107
108 }
109 func (b *Boss) Rest() {
110 fmt.Println("一天到晚都在休息")
111 }
112
113 /*
114 今天是星期1
115 码农一天工作8小时
116 码农正在撸代码
117 产品一天工作8小时
118 产品正在拍脑门
119 老板一天工作8小时
120 老板正在吹牛逼
121
122
123 今天是星期0
124 休息是什么?
125 看程序员卤代码
126 一天到晚都在休息
127 */
4 类型检测 类型断言 类型判断
1 package main
2
3 import (
4 "fmt"
5 )
6
7 func main() {
8 //创建Worker组成的切片
9 workers := make([]Worker, 0)
10
11 //添加有问题 cannot use Coder literal (type *Coder) as type Worker in append:
12 workers = append(workers, &Coder{"撸代码"})
13 workers = append(workers, &ProductManager{"拍脑门"})
14 workers = append(workers, &Boss{"吹牛逼"})
15
16 //类型检测 类型断言 类型判断 方式01
17 for _, worker := range workers {
18 switch worker.(type) {
19 case *Coder:
20 fmt.Println("代码代码代码")
21 case *ProductManager:
22 fmt.Println("需求需求需求")
23 case *Boss:
24 fmt.Println("梦想梦想梦想")
25
26 }
27 }
28 /*
29 代码代码代码
30 需求需求需求
31 梦想梦想梦想
32 */
33
34 //类型检测 类型断言 类型判断 方式02
35 for _, worker := range workers {
36 if coder, ok := worker.(*Coder); ok {
37 fmt.Println("发现一个程序员", coder)
38 coder.WorkHome()
39 } else {
40 fmt.Println("不是程序员")
41 }
42 }
43
44 }
45
46 //劳动者父类接口
47 //内含俩个抽象方法:工作,休息.
48 type Worker interface {
49 //每天工作多少小时,产出何种产品
50 Work(hour int) (product string) //定义了一个方法没有做实现,就是接口
51
52 //休息
53 Rest() //定义了一个方法没有做实现,就是接口
54 }
55
56 //程序员
57 type Coder struct {
58 skill string
59 }
60
61 //程序员指针实现Worker接口,因为这里写的WOrk和Rest方法写的和上面定义的一致,所以就可以说 程序员实现了工人这个接口。
62 func (c *Coder) Work(hour int) (product string) {
63 fmt.Printf("码农一天工作%d小时
", hour)
64 fmt.Printf("码农正在%s
", c.skill)
65 return "BUG"
66 }
67
68 //程序员休息的方法
69 func (c *Coder) Rest() {
70 fmt.Println("休息是什么?")
71 }
72
73 //程序员特有方法
74 func (c *Coder) WorkHome() {
75 fmt.Println("程序员在家工作")
76 }
77
78 //产品经理
79 type ProductManager struct {
80 skill string
81 }
82
83 //ProductManager指针实现worker接口
84 func (pm *ProductManager) Work(hour int) (product string) {
85 fmt.Printf("产品一天工作%d小时
", hour)
86 fmt.Printf("产品正在%s
", pm.skill)
87 return "无逻辑的需求"
88
89 }
90
91 func (pm *ProductManager) Rest() {
92 fmt.Println("看程序员卤代码")
93 }
94
95 //老板
96 type Boss struct {
97 skill string
98 }
99
100 //Boss指针实现Worker接口
101 func (b *Boss) Work(hour int) (product string) {
102 fmt.Printf("老板一天工作%d小时
", hour)
103 fmt.Printf("老板正在%s
", b.skill)
104 return "梦想"
105
106 }
107 func (b *Boss) Rest() {
108 fmt.Println("一天到晚都在休息")
109 }
110
111 /*
112 代码代码代码
113 需求需求需求
114 梦想梦想梦想
115 发现一个程序员 &{撸代码}
116 程序员在家工作
117 不是程序员
118 不是程序员
119 */
5 接口的继承
1 package main
2
3 import "fmt"
4
5 //定义两个父类接口
6 //定义动物接口:所有动物都会新陈代谢,都会挂掉
7 type Animal interface {
8 //新陈代谢:吃进来+排出去,shit就是翔啊~
9 Eat(food string) (shit string)
10 //GAME OVER
11 Die()
12 }
13
14 //定义战士接口,会进攻和防守
15 type Fighter interface {
16 //进攻并造成对手掉血
17 Attack() (bloodLoss int)
18 Defend()
19 }
20
21 //显式地继承父类接口
22 //野兽接口,拥有动物的一切特征
23 //野兽接口,拥有战士的一切特征
24 type Beast interface {
25 //野兽接口继承动物接口
26 Animal
27 //野兽接口继承斗士接口
28 Fighter
29 Run()
30 }
31
32 //隐式继承父类接口
33 type Beasts interface {
34 //显式继承动物接口
35 Animal
36
37 //隐式继承斗士接口:没有明确地说继承斗士,但事实上定义了其全部抽象方法
38 Attack() (bloodLoss int)
39 Defend()
40
41 //野兽特有的方法
42 Run()
43 }
44
45 //实现Beast接口
46 type Tiger struct {
47 name string
48 food string
49 shit string
50 power int
51 }
52
53 /*实现野兽的全部方法才算是野兽*/
54 func (t *Tiger)Eat(food string) (shit string) {
55 fmt.Printf("本王正在享用%s,并撇下%s
",t.food,t.shit)
56 return t.shit
57 }
58 func (t *Tiger)Die() {
59 fmt.Printf("大猫%s也有狗带的一天啊,啊啊啊啊...
",t.name)
60 }
61 func (t *Tiger)Attack() (bloodLoss int) {
62 fmt.Printf("本王咬你,掉血%d毫升
",t.power)
63 return t.power
64 }
65 func (t *Tiger)Defend() {
66 fmt.Println("躺在地上举高高,我不是在卖萌,而是在防守")
67 }
68 func (t *Tiger)Run() {
69 fmt.Println("本王在奔跑")
70 }
71
72 //使用接口实例
73
74 func main() {
75
76 tiger := &Tiger{"东北虎", "其它野兽", "虎翔", 1024}
77
78 var animal Animal
79 var fighter Fighter
80 var beast Beast
81
82 //老虎既是动物,又是斗士,又是野兽
83 //用子类实现去给父类接口赋值
84 animal = tiger
85 fighter = tiger
86 beast = tiger
87
88 //调用父类接口方法
89 animal.Eat("食物")
90 animal.Die()
91 fighter.Attack()
92 fighter.Defend()
93 beast.Run()
94 }
综合练习
1 /*
2 定义动物接口: 死亡,活着
3 定义动物实现类: 鸟,鱼,野兽(跑,捕食)
4 继承野兽,实现老虎,实现人。
5 业务场景,工作日所有动物都活着,周末人出来捕食,野兽淘跑,其他动物死光光.
6 */
7
8 package main
9
10 import (
11 "fmt"
12 "math/rand"
13 "time"
14 )
15
16 func main() {
17 //创建生态
18 bird := Bird{}
19 fish := Fish{}
20 tiger := Tiger{Beast{}}
21 human := Human{Beast{}, "张三"}
22
23 animals := make([]Animal, 0)
24 animals = append(animals, &bird)
25 animals = append(animals, &fish)
26 animals = append(animals, &tiger)
27 animals = append(animals, &human)
28
29 r := rand.New(rand.NewSource(time.Now().UnixNano()))
30 weekday := r.Intn(7)
31 fmt.Printf("今天是星期%d
", weekday)
32
33 if weekday > 0 && weekday < 6 {
34 for _, animal := range animals {
35 animal.Live()
36 }
37 } else {
38 for _, animal := range animals {
39 switch animal.(type) {
40 case *Human:
41 //将人转换为野兽,并令其捕食.
42 animal.(*Human).Hunt()
43 case *Tiger:
44 animal.(*Tiger).Run()
45 default:
46 animal.GoDie()
47
48 }
49 }
50 }
51
52 }
53
54 //接口
55 type Animal interface {
56 GoDie()
57 Live()
58 }
59
60 //劳动者接口
61 type Labor interface {
62 Work()
63
64 }
65
66
67 //鸟结构体
68 type Bird struct{}
69
70 func (b *Bird) Live() {
71 fmt.Println("一只鸟在唱歌")
72 }
73
74 func (b *Bird) GoDie() {
75 fmt.Println("一只鸟死翘翘")
76 }
77
78 //鱼结构体
79 type Fish struct{}
80
81 func (f *Fish) Live() {
82 fmt.Println("一只鱼在游泳")
83 }
84
85 func (f *Fish) GoDie() {
86 fmt.Println("一只鱼死翘翘")
87 }
88
89 //野兽结构体
90 type Beast struct{}
91
92 func (c *Beast) Live() {
93 fmt.Println("一只野兽在唱歌")
94 }
95
96 func (c *Beast) GoDie() {
97 fmt.Println("一只野兽死翘翘")
98 }
99
100 func (c *Beast) Run() {
101 fmt.Println("一只野兽在奔跑")
102 }
103
104 func (c *Beast) Hunt() {
105 fmt.Println("一只野兽在捕捉食物")
106 }
107
108 //老虎结构体
109 type Tiger struct {
110 Beast
111 }
112
113 func (c *Tiger) Hunt() {
114 fmt.Println("本王要吃饭了..")
115 }
116
117 //人结构体
118 type Human struct {
119 Beast
120 name string
121 }
122 func (c *Human) Live() {
123 fmt.Println("一枚人类在好好工作...")
124 }
125
126
127 func (c *Human) Hunt() {
128 fmt.Println("一类人类,该吃饭了..")
129 }
130 /*
131 今天是星期5
132 一只鸟在唱歌
133 一只鱼在游泳
134 一只野兽在唱歌
135 一枚人类在好好工作...
136
137 今天是星期6
138 一只鸟死翘翘
139 一只鱼死翘翘
140 一只野兽在奔跑
141 一类人类,该吃饭了..
142
143
144
145 */