## golang面对对象编程
特点:继承/封装/多态
- 封装:通过方法实现
- 继承:通过匿名字段实现
- 多态:通过接口实现
1. 匿名字段
```
type Person struct {
code int //编码
sex byte //性别
name string //姓名
age int //年龄
}
type Student struct {
Person
class string
addr string
}
func main() {
s1 := Student{Person: Person{code: 1, sex: 1, name: ""}, class: "一(2)班", addr: "sz"}
//%+v 显示更详细
fmt.Printf("%+v", s1)
}
```
2. 同名字段
就近原则
```
//同名字段 就近原则
s1.name="888888888888"
//显示调用
s1.Person.name="99999999"
fmt.Printf("%+v \n", s1)
```
3. 非结构体匿名字段
...
4. 方法
面向对象 方法 :给某个类型绑定函数
==接收者可以是指针 类型本身不能是指针==
//带有接收者的函数叫方法
```
func (tmp student) printInfo() {
fmt.Printf("%+v \n", tmp)
}
```
> 方法名相同,只要接收者类型不一样,他们就是两个不同的方法
```
//方法名相同,只要接收者类型不一样,他们就是两个不同的方法
func (tmp student) printInfo() {
fmt.Printf("%+v \n", tmp)
}
func (tmp person) printInfo() {
fmt.Printf("%+v \n", tmp)
}
```
5. 给结构体添加方法
```
type student struct {
code int //编码
name string //姓名
class string //班级
age int //年龄
}
//带有接收者的函数叫方法
func (tmp student) printInfo() {
fmt.Printf("%+v \n", tmp)
}
//通过函数给成员赋值
func (p *student) setInfo(code int, name string, class string, age int) {
p.class = class
p.name = name
p.code = code
p.age = age
}
func main() {
s1 := student{code: 001, name: "tomLiu", class: "小班"}
s1.printInfo()
var s2 student
(&s2).setInfo(1,"刘子琪","大1班",5)
s2.printInfo()
}
```
6. 值传递和引用语义
//接收者为普通变量,非指针,值语义,拷贝
//接收者为指针变量,引用传递
7. 指针变量的方法集
用实例实例 value 和 pointer 调用方法(含匿名字段)不受⽅法集约束,编译器编总是查找全部方法,并自动转换 receiver 实参。
不管接收者是变量还是指针 变量和指针类型都可以调用方法,效果一样
8. 方法的继承
如果匿名字段实现了一个方法,那么包含这个匿名字段的struct也能调用该方法
9. 方法的重写
```
type person struct {
code int //编码
name string //姓名
}
type student struct {
person
class string //班级
}
func (tmp *person) printInfo(){
fmt.Println(tmp)
}
func (tmp *student) printInfo(){
fmt.Println(tmp)
}
func main() {
var s1 student=student{person:person{
code: 123,
name: "tom",
},class: "计算机科学三年级一班"}
s1.printInfo()
}
```
10. 方法值和方法表达式
> 方法值 保存方法入口地址
方法表达式 显示把接收者传过去
```
p:=person{code:1,name:"tom"}
//方法值 保存方法入口地址
pPrint:=p.printInfo
pPrint()//通过pPrint就可以直接调用p.printInfo,隐藏了接收者
//方法表达式 显示把接收者传过去
f:=(*person).printInfo
f(&p)
```
11. ==接口==
在Go语言中,接口(interface)是一个自定义类型,接口类型具体描述了一系列方法的集合。
接口类型是一种抽象的类型,它不会暴露出它所代表的对象的内部值的结构和这个对象支持的基础操作的集合,它们只会展示出它们自己的方法。因此接口类型不能将其实例化。
Go通过接口实现了鸭子类型(duck-typing):“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子”。我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。
12. 接口定义
```
type Humaner interface {
SayHi()
}
```
13. 接口实现
接口是用来定义行为的类型。这些被定义的行为不由接口直接实现,而是通过方法由用户定义的类型实现,一个实现了这些方法的具体类型是这个接口类型的实例。
如果用户定义的类型实现了某个接口类型声明的一组方法,那么这个用户定义的类型的值就可以赋给这个接口类型的值。这个赋值会把用户定义的类型的值存入接口类型的值。
14. 接口嵌入
```
type Humaner interface {
SayHi()
}
type Personer interface {
Humaner //这里想写了SayHi()一样
Sing(lyrics string)
}
type Student struct { //学生
name string
score float64
}
//Student实现SayHi()方法
func (s *Student) SayHi() {
fmt.Printf("Student[%s, %f] say hi!!\n", s.name, s.score)
}
//Student实现Sing()方法
func (s *Student) Sing(lyrics string) {
fmt.Printf("Student sing[%s]!!\n", lyrics)
}
func main() {
s := &Student{"mike", 88.88}
var i2 Personer
i2 = s
i2.SayHi() //Student[mike, 88.880000] say hi!!
i2.Sing("学生哥") //Student sing[学生哥]!!
}
```
15. 接口转换
> 超集可以转换成子集,子集不能转换成超集
16. 空接口
空接口是一个万能接口,他可以转换成任何接口
空接口(interface{})不包含任何的方法,正因为如此,所有的类型都实现了空接口,因此空接口可以存储任意类型的数值。它有点类似于C语言的void *类型。
```
func Printf(fmt string, args ...interface{})
func Println(args ...interface{})
```
17. 类型断言
通过switch判断是什么类型
> switch data.(type) {case int :}
```
//判断是否是什么类型
switch data.(type) {
case int :
fmt.Printf("i[%d] 类型是int 内容为%d\n",i,data)
case string :
fmt.Printf("i[%d] 类型是string 内容为%s\n",i,data)
case Student :
fmt.Printf("i[%d] 类型是Student 内容为%+v\n",i,data)
case map[int]Student :
fmt.Printf("i[%d] 类型是map 内容为%+v\n",i,data)
default:
fmt.Printf("i[%d] 类型是%T 内容为%+v\n",i,data,data)
}
```
---
> if value, ok := data.(int); ok == true {}
通过if判断
```
//判断是否是某类型
if value, ok := data.(int); ok == true {
fmt.Printf("i[%d] 类型是int 内容为%d\n", i, value)
} else if value, ok := data.(string); ok == true {
fmt.Printf("i[%d] 类型是string 内容为%s\n", i, value)
} else if value, ok := data.(Student); ok == true {
fmt.Printf("i[%d] 类型是Student 内容为%+v\n", i, value)
} else if value, ok := data.(map[int]Student); ok == true {
fmt.Printf("i[%d] 类型是map 内容为%+v\n", i, value)
} else {
fmt.Printf("i[%d] 类型是%T 内容为%+v\n", i, value, value)
}
```
有疑问加站长微信联系(非本文作者)