#### Go 多态
前面两节学习了Go 的继承,接口;那么继承和接口有什么不同呢? 下面我们一起来探讨一下:
继承的价值主要在于: 解决代码的复用性和可维护性;
接口的价值主要在于: 设计,接口设计好各种规范方法,让其它自定义类型实现这些方法
接口比继承更加灵活,继承是满足is-a 的关系,接口是满足like-a 的关系;
下面一起来学习一下多态
变量具有多种形态, 是面向对象编程的第三大特征,Go 中的多态是通过接口实现的;
package main import "fmt" type USB interface { Start() Stop() } type Phone struct {} type Camera struct {} func (p *Phone) Start(){ fmt.Println("phone is working") } func (p *Phone) Stop(){ fmt.Println("phone stop work") } func (c *Camera) Start(){ fmt.Println("camera is working") } func (c *Camera) Stop(){ fmt.Println("camera stop work") } func working(usb USB) { usb.Start() usb.Stop() } func main(){ var phone = new(Phone) var camera = new(Camera) working(phone) working(camera) }
说明:
wroking 方法即可以接收Phone 类型的变量,也可以接收Camera 类型的变量,体现出了USB 接口的多态
接口多态有以下两种形式:
1. 多态参数: 比如上面的例子
2. 多态数组或切片
var USBArray [3]USB USBArray[0] = &Phone{} USBArray[1] = &Camera{}
##### 类型断言
如何将一个接口类型的数据,赋值给具体类型? 需要使用到类型断言;
package main import "fmt" func main(){ var a interface{} var b int b = 10 a = b // 空接口可以接收任意类型的数据 fmt.Println(a) //var c int //c = a // 错误,不能将空接口类型直接赋值给具体的类型, 需要使用类型断言 if c,ok := a.(int);ok { // 在进行类型断言时,如果类型不匹配,会panic // 所以在进行类型断方时需要确保空接口指向的就是断言的类型 // 在进行类型断言时可以加上检测机制,就算断言不成功也不会报panic fmt.Println("assert right") fmt.Println(c) } else { fmt.Println("assert failed") } }
##### 类型断言的使用案例
package main import "fmt" // 编写一下函数,可以接收任意类型的数据 func typeAssert(data interface{}) { switch data.(type) { case bool: fmt.Println("data type is bool") case string: fmt.Println("data type is string") case float64: fmt.Println("data type is float64") case float32: fmt.Println("data type is float32") case int,int64: fmt.Println("data type is int") default: fmt.Println("data type is unknow") } } func main() { var a bool var b string var c float64 var d float32 var e int var f int64 typeAssert(a) typeAssert(b) typeAssert(c) typeAssert(d) typeAssert(e) typeAssert(f) }
案例2:
package main import "fmt" type USB interface { Start() Stop() } type Phone struct { Name string } type Camera struct { Name string } func (p *Phone) Start(){ fmt.Println(p.Name,"is working") } func (p *Phone) Stop(){ fmt.Println(p.Name,"stop work") } func (p *Phone) Call(){ fmt.Println(p.Name,"is calling") } func (c *Camera) Start(){ fmt.Println(c.Name,"is working") } func (c *Camera) Stop(){ fmt.Println(c.Name,"stop work") } func (c *Camera) Shoot(){ fmt.Println(c.Name,"is shooting") } func work(usb USB) { usb.Start() // 实际类型实现接口还有其它的方法 if phone,ok := usb.(*Phone);ok { phone.Call() } if camera,ok := usb.(*Camera);ok { camera.Shoot() } usb.Stop() } func main(){ var phone = &Phone{Name:"apple"} var camera = &Camera{Name:"nikon"} work(phone) work(camera) }
今天就写这么多吧, Go 基本语法部分大概学习完了,学习完这部分后
大家可以尝试做一些小项目,巩固一下基础知识;后面还有单元测试,协程,通道,反射四个基础章节;
学习完最后四个章节后,会介绍一些Go 的生态以及平常工作中使用到的类库;
个人微信公众号上有最新文章,欢迎关注一同交流学习