Go 多态

#### 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 的生态以及平常工作中使用到的类库;

个人微信公众号上有最新文章,欢迎关注一同交流学习


posted @ 2019-09-09 16:48  mail_maomao  阅读(498)  评论(0编辑  收藏  举报