1763 字
9 分钟
Go 语言学习笔记 -第16章

Go 语言学习笔记 -第16章#

结构体#

封装#

model/model.go

package model
import "fmt"
//结构体开头首字母小写
type person struct {
Name string
age int //变量小写其他包不能直接访问
sal float64
}
//写一个工厂函数,相当于构造函数
func NewPerson(name string) *person {
return &person{
Name: name,
}
}
//为了访问sage, salary编写一对get/set方法
func (p *person) SetAge(age int) {
if age > 0 && age < 150 {
p.age = age
} else {
fmt.Println("年龄范围不正确")
}
}
func (p *person) GetAge() int {
return p.age
}
func (p *person) SetSal(sal float64) {
if sal > 3000 && sal <= 30000 {
p.sal = sal
} else {
fmt.Println("薪水范围不正确")
}
}
func (p *person) GetSal() float64 {
return p.sal
}

main/main.go

package main
import (
"fmt"
"prj/model"
)
func main() {
p := model.NewPerson("smith")
p.SetAge(18)
p.SetSal(5000)
fmt.Println(p.Name, "age=", p.GetAge(), "sal=", p.GetSal())
}

继承#

1.普通方法

package main
import (
"fmt"
)
//小学生
type Pupil struct {
Name string
Age int
Score int
}
func (p *Pupil) ShowInfo() {
fmt.Printf("学生名=%v 年龄=%v 成绩=%v\n", p.Name, p.Age, p.Score)
}
func (p *Pupil) SetScore(score int) {
p.Score = score
}
func (p *Pupil) testing() {
fmt.Println("小学生正在考试...")
}
//大学生
//研究生
func main() {
//测试
var pupil = &Pupil{
Name: "tom",
Age: 10,
}
pupil.testing()
pupil.SetScore(90)
pupil.ShowInfo()
}

2.继承写法

package main
import (
"fmt"
)
type Student struct {
Name string
Age int
Score int
}
func (stu *Student) ShowInfo() {
fmt.Printf("学生名=%v 年龄=%v 成绩=%v\n", stu.Name, stu.Age, stu.Score)
}
func (stu *Student) SetScore(score int) {
stu.Score = score
}
//小学生
type Pupil struct {
Student //嵌入Student匿名结构体
}
func (p *Pupil) testing() {
fmt.Println("小学生正在考试...")
}
//大学生
type Graduate struct {
Student
}
func (p *Graduate) testing() {
fmt.Println("大学生正在考试...")
}
//研究生
func main() {
//测试
var pupil = &Pupil{}
pupil.Student.Name = "tom"
pupil.Student.Age = 10
pupil.testing()
pupil.Student.SetScore(90)
pupil.Student.ShowInfo()
var graduate = &Graduate{}
graduate.Student.Name = "Mary"
graduate.Student.Age = 20
graduate.testing()
graduate.Student.SetScore(60)
graduate.Student.ShowInfo()
}

注意事项:

事项1:

package main
import (
"fmt"
)
type A struct {
Name string
age int //小写也是可以继承的
}
func (a *A) SayOk() {
fmt.Println("A sayok")
}
func (a *A) hello() {
fmt.Println("A hello")
}
type B struct {
A
}
func main() {
var b B
// b.A.Name = "tom" //也可以写成b.Name = "tom"
// b.A.age = 19 //也可以写成b.age = 19
b.Name = "Smith"
b.age = 10
b.SayOk()
b.hello()
// b.A.SayOk() //也可以写成b.SayOk()
// b.A.hello()//也可以写成b.hello()
}

事项2:

package main
import (
"fmt"
)
type A struct {
Name string
age int //小写也是可以继承的
}
func (a *A) SayOk() {
fmt.Println("A sayok", a.Name)
}
func (a *A) hello() {
fmt.Println("A hello", a.Name)
}
type B struct {
A
Name string //相同字段就近原则
}
func (b *B) SayOk() {
fmt.Println("B sayok", b.Name)
}
func main() {
var b B
b.Name = "Smith"
b.A.Name = "jack"
b.SayOk() //B sayok Smith
b.hello() //A hello
}

事项3:

package main
import "fmt"
type A struct {
Name string
age int
}
type B struct {
Name string
age int
}
type C struct {
A
B
Name string
}
func main() {
var c C
c.Name = "tom" //?
//如果C没有Name字段,而A和B有Name,则要指定匿名结构体来区分
//c.Name ==> c.A.Name, 这个规则对方法也是一样的
fmt.Println("c=", c)
}

事项4:

package main
import "fmt"
type A struct {
Name string
age int
}
type B struct {
Name string
age int
}
type C struct {
A
B
}
type D struct {
a A //有名结构体 组合关系
// Name string
}
func main() {
var d D
// d.Name = "jack" //报错,需要写成d.a.Name
//如果D是一个有名结构体,访问要带上有名结构体的名字
//需要写成d.a.Name
d.a.Name = "jack"
fmt.Println("d=", d)
}

事项5:

package main
import "fmt"
type Goods struct {
Name string
Price float64
}
type Brand struct {
Name string
Address string
}
type TV struct {
Goods
Brand
}
type TV2 struct {
*Goods
*Brand
}
func main() {
tv := TV{Goods{"电视机001", 5000.99}, Brand{"海尔", "山东"}}
// tv := TV{
// Goods{
// Name: "电视机001",
// Price: 5000.99,
// },
// Brand{
// Name: "海尔",
// Address: "山东",
// },
// }
tv2 := TV2{&Goods{"电视机002", 9999.99}, &Brand{"创维", "河南"}}
fmt.Println("tv=", tv)
fmt.Println("tv2=", *tv2.Goods, *tv2.Brand)
}

事项6:

package main
import "fmt"
type Goods struct {
Name string
Price float64
}
type TV struct {
Goods
int //匿名字段
// int
n int
}
func main() {
var tv TV
tv.Name = "aaa"
tv.Price = 100
tv.int = 20
tv.n = 40
fmt.Println("tv=", tv)
}

多态#

package main
import (
"fmt"
)
//Usb 声明
//接口体现多态、高内聚低耦合思想
type Usb interface {
//声明两个没有实现的方法
//根据方法来判断
Start()
Stop()
}
//手机
type Phone struct {
}
//让Phone实现Usb接口的方法
func (p Phone) Start() {
fmt.Println("手机开始工作...")
}
func (p Phone) Stop() {
fmt.Println("手机停止工作...")
}
//照相机
type Camera struct {
}
//让Camera实现Usb接口的方法
func (c Camera) Start() {
fmt.Println("相机开始工作...")
}
func (c Camera) Stop() {
fmt.Println("相机停止工作...")
}
//计算机
type Computer struct {
}
//编写working方法,接收一个Usb接口类型变量
//只要是实现了Usb接口: 就是实现了Usb接口声明所有方法
func (c Computer) Working(usb Usb) {
usb.Start()
usb.Stop()
}
func main() {
computer := Computer{}
phone := Phone{}
// camera = Camera{}
computer.Working(phone)
}

说明:

这里的Usb usb,既可以接收手机变量、又可以接收相机变量,就体现了Usb接口多态特性

接口体现多态特征

1、多态参数 如Usb usb

2、多态数组

package main
import (
"fmt"
)
//Usb 声明
//接口体现多态、高内聚低耦合思想
type Usb interface {
//声明两个没有实现的方法
//根据方法来判断
Start()
Stop()
}
//手机
type Phone struct {
name string
}
//让Phone实现Usb接口的方法
func (p Phone) Start() {
fmt.Println("手机开始工作...")
}
func (p Phone) Stop() {
fmt.Println("手机停止工作...")
}
//照相机
type Camera struct {
name string
}
//让Camera实现Usb接口的方法
func (c Camera) Start() {
fmt.Println("相机开始工作...")
}
func (c Camera) Stop() {
fmt.Println("相机停止工作...")
}
func main() {
//定义usb接口数组,多态数组
var usbArr [3]Usb
usbArr[0] = Phone{"vivo"}
usbArr[1] = Phone{"小米"}
usbArr[2] = Camera{"尼康"}
fmt.Println(usbArr)
}

golang接口和继承的关系#

package main
import "fmt"
type Monkey struct {
Name string
}
type LittleMonkey struct {
Monkey
}
//声明接口
type BirdAble interface {
Flying()
}
type FishAble interface {
Swimming()
}
func (this *Monkey) climbing() {
fmt.Println(this.Name, "生来会爬树...")
}
//让littleMoney实现BirdAble
func (this *LittleMonkey) Flying() {
fmt.Println(this.Name, "通过学习会飞翔...")
}
func (this *LittleMonkey) Swimming() {
fmt.Println(this.Name, "通过学习会游泳...")
}
func main() {
monkey := LittleMonkey{
Monkey{
Name: "悟空",
},
}
monkey.climbing()
monkey.Flying()
monkey.Swimming()
}

总结:

1.当A结构体继承了B结构体,那么A结构体自动继承了B结构体的字段和方法,并且可以直接使用

2.当A结构体需要扩展功能,同时不希望区破坏继承关系,则可以去实现某个接口,因此我们可以认为,实现接口是对继承机制的补充

3.接口和继承解决的问题不同 1)继承的价值主要在于:解决代码的复用性和可维护性 2)接口的价值主要在于:设计,设计好各种规范(方法),让其他自定义类型去实现这些方法

4.接口比继承更加灵活 继承是满足 is -a的关系 Person- Student 接口只需满足 like -a的关系 BirdAble LittleMoney

5.接口在一定程度上实现代码解耦

Go 语言学习笔记 -第16章
https://blog.zhequtao.com/posts/golang/go-learning/学习笔记-go/第16章/
作者
阿俊
发布于
2020-03-30
许可协议
CC BY-NC-SA 4.0

相关阅读