面对对象
面对对象介绍
/* 面向对象的三大特性或四大特性: 封装: 化繁为简,将业务相近的变量,函数封装为结构体(类),减少直接管理的成员数,便于做大规模开发。 继承:将公共的部分提取到父类,减少重复代码,继承另外便于扩展和覆写修改类方法 多态: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爱吃..\n", p.name) 22 23 } 24 25 func (p *Person) Drink() { 26 fmt.Printf("%s爱喝..\n", 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爱吃..\n", p.name) 16 17 } 18 19 func (p *Person) Drink() { 20 fmt.Printf("%s爱喝..\n", p.name) 21 22 } 23 24 func (p *Person) jieshao() { 25 fmt.Printf("我是%s,今年%d岁了\n", 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爱吃..\n", 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爱吃..\n", p.name) 8 9 } 10 11 //会喝 12 func (p *person) Drink() { 13 fmt.Printf("%s爱吃..\n", p.name) 14 15 } 16 17 //会爱爱 18 func (p *person) Love() { 19 fmt.Printf("%s爱美女..\n", 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爱喝酒\n", 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\n", r.ReaderID, b.Name) 24 } else { 25 fmt.Printf("读者%s借阅失败,%s已被借出..\n", r.ReaderID, b.Name) 26 } 27 } 28 29 //还书方法 30 func (r *Reader) ReturnBook(b *Book) { 31 fmt.Printf("读者%s归还了%s\n", 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\n", r.ReaderID, amount, r.Balance) 39 40 } 41 42 //覆写交罚金方法.老师不存在交罚金 43 func (t *Teacher) PayPenalty(amount float64) { 44 fmt.Printf("读者%s缴纳了%.2f元,余额是%.2f\n", 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\n",s1) //正常输出 104 //fmt.Printf("%+v\n",s1) //详细输出 105 //fmt.Printf("%#v\n",s1) //超详细输出 106 107 //创建老师 108 t1 := Teacher{Reader{"001", 0}, "李老师", "go"} 109 fmt.Printf("%+v\n", 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\n", 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小时\n", hour) 66 fmt.Printf("码农正在%s\n", 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小时\n", hour) 88 fmt.Printf("产品正在%s\n", 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小时\n", hour) 105 fmt.Printf("老板正在%s\n", 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小时\n", hour) 64 fmt.Printf("码农正在%s\n", 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小时\n", hour) 86 fmt.Printf("产品正在%s\n", 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小时\n", hour) 103 fmt.Printf("老板正在%s\n", 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\n",t.food,t.shit) 56 return t.shit 57 } 58 func (t *Tiger)Die() { 59 fmt.Printf("大猫%s也有狗带的一天啊,啊啊啊啊...\n",t.name) 60 } 61 func (t *Tiger)Attack() (bloodLoss int) { 62 fmt.Printf("本王咬你,掉血%d毫升\n",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\n", 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 */