• Go 接口


    #### Go 接口
    上一节学习了Go 的封装和继承, 这一节来学习一下多态, 在Go 中多态是通过接口实现的, 所以先来学习一下接口
    先来学习一个案例:
    package main
    
    import "fmt"
    // 定义一个接口
    type USB interface {
       Start()
       Stop()
    }
    type Phone struct {}
    type Camera struct {}
    // Phone 实现USB 接口中的方法
    func (p *Phone) Start(){
       fmt.Println("phone is working")
    }
    func (p *Phone) Stop(){
       fmt.Println("phone stop work")
    }
    // Camera 实现USB 接口中的方法
    func (c *Camera) Start(){
       fmt.Println("camera is working")
    }
    func (c *Camera) Stop(){
       fmt.Println("camera stop work")
    }
    // 接收一个USB interface 调用接口中的方法
    func Working(usb USB) {
       usb.Start()
       usb.Stop()
    }
    func main(){
       var phone = new(Phone)
       var camera = new(Camera)
       Working(phone)
       Working(camera)
    }
    

      


    ---
    ###### 接口的概念
    interface 类型可以定义一组方法,但是这些方法不需要实现,并且interface 不能包含任何变量,当某个自定义类型需要使用接口的时候,把接口
    中定义的方法实现;
    基本语法:
    type 接口名 interface {
    方法01(参数列表) 返回值列表
    方法02(参数列表) 返回值列表
    ...
    }
    方法的实现:
    func (a 自定义类型) 方法01(参数列表) 返回值列表{
    方法内容的具体实现
    }
    func (a 自定义类型) 方法02(参数列表) 返回值列表{
    方法内容的具体实现
    }
    ---
    说明:
    1. 接口中的***所有方法都没有方法体***,即接口中的方法都是没有实现的方法,体现了程序设计的多态思想;
    2. Go 中的接口***不需要显示的实现***,只要一个自定义类型实现了接口类型中的所有方法,那么这个自定义变量
    就实现了这个接口;
    3. 接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量;
    4. 一个自定义类型只有将接口中的所有方法都实现了才能称之为实现了该接口;
    5. 一个自定义类型只有实现了某个接口,才能将该自定义类型的变量赋给接口类型;
    6. 自定义类型不局限于结构体, 可以是任意的自定义的数据类型;
    7. 一个自定义类型可以实现多个接口;
    8. 接口中不能有任何变量;
    9. 接口类型是指针类型(也可称为引用类型);
    10. 空接口没有任何方法***所有的类型都实现了空接口***,所以可以把任何一个变量都可以赋值给空接口;
    11. 一个接口(A)可以继承其它的接口(B,C...),如果要实现A接口, 需要将它继承的接口(B,C...)也全部实现;
    package main
    
    import "fmt"
    
    type Personer interface {
       // 1. 接口中所有的方法都没有方法体
       // 8. 接口中不能有变量
       // Name string
       Eat()
       Speak()
    }
    type Animaler interface {
       Walk()
    }
    // 接口继承其它接口
    type Childer interface {
       Personer
       Cry()
    }
    // 父结构体
    type Person struct {
       Name string
    }
    // 继承Person
    type Student struct {
       Person
    }
    // 继承Person
    type Teacher struct {
       Person
    }
    // 继承Person
    type Child struct {
       Person
    }
    // 自定义数据类型,相当于给string 类型定义一个别名
    type MyData string
    // Student 实现接口中的方法
    func (s *Student) Eat(){
       fmt.Printf("[Student] %s is eatting 
    ",s.Name)
    }
    func (s *Student) Speak(){
       fmt.Printf("[Student] %s is speaking 
    ",s.Name)
    }
    // Teacher 实现接口中的方法之一
    // 只有实现了接口中的所有方法才能称为实现了该接口
    func (t *Teacher) Eat(){
       fmt.Printf("[Teacher] %s is eatting 
    ",t.Name)
    }
    // MyData 实现接口中的方法
    func (m *MyData) Eat(){
       fmt.Printf("[MyData] is eatting 
    ")
    }
    func (m *MyData) Speak(){
       fmt.Printf("[MyData] is speaking 
    ")
    }
    // 7. MyData 实现多个接口
    func (m *MyData) Walk(){
       fmt.Printf("[MyData] is walking 
    ")
    }
    // 11. 如果要实现Childer 接口必须要实现Personer中的方法
    func (c *Child) Eat(){
       fmt.Printf("[Child] %s is eatting 
    ",c.Name)
    }
    func (c *Child) Speak(){
       fmt.Printf("[Child] %s is speaking 
    ",c.Name)
    }
    func (c *Child) Cry(){
       fmt.Printf("[Child] %s is crying 
    ",c.Name)
    }
    func main(){
       var p Personer
       var s = new(Student)
       // 3. 接口类型本身不能创建实例
       // p.Eat()
       // 也就是说在没有给接口赋值前不能直接通过接口调用接口中的方法
    
       // 2. 只要实现了接口类型中所有的方法,就可以赋值给接口类型
       p = s
       p.Eat()
    
       // 4/5. 错误, 只有实现了接口中所有的方法才能赋值给接口类型
       //var t = new(Teacher)
       //p = t
    
       // 6. 自定义数据类型不局限于结构体
       var m = new(MyData)
       p = m
       p.Eat()
    
       //9. 接口是指针类型
       var p2 Personer
       fmt.Printf("%T
    ",p2) // 默认值为nil
    
       //10. 可以把任何变量赋值给空接口
       var a interface{}
       var b = "hello,world"
       a = b
       fmt.Println(a)
    
       // 11.
       var c Childer
       var child = new(Child)
       c = child
       c.Cry()
       c.Eat()
    }
    

      


    接口实际应用的小例子:
    package main
    
    import (
       "fmt"
       "sort"
    )
    // 自定义类型实现sort.Interface 接口
    type MySort []string
    func (m MySort) Len() int { return len(m)}
    func (m MySort) Swap(i,j int) {m[i],m[j] = m[j],m[i]}
    func (m MySort) Less(i,j int) bool {
       // 先比较年
       i_year := m[i][6:]
       j_year := m[j][6:]
       if i_year < j_year {
          return true
       } else if i_year > j_year {
          return false
       } else {
          // 再比较月
          i_mon := m[i][3:5]
          j_mon := m[j][3:5]
          if i_mon < j_mon {
             return true
          } else if i_mon > j_mon {
             return false
          } else {
             // 比较日期
             if m[i][:2] < m[j][:2] {
                return true
             } else if m[i][:2] > m[j][:2] {
                return false
             } else {
                return true
             }
          }
       }
    }
    func main(){
       var strSlice = []string{
          // 月/日/年
          "08/01/2018",
          "05/01/2019",
          "22/06/2018",
          "08/02/2019",
          "22/12/2018",
       }
       // 排序前
       fmt.Println(strSlice)
       // 调用sort 包排序
       // 排序后的结果与预想中并不一样
       sort.Strings(strSlice)
       fmt.Println(strSlice)
       // 自定义类型实现sort.Interface 中的方法,实现自定义排序
       sort.Sort(MySort(strSlice))
       fmt.Println(strSlice)
    }
    

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

  • 相关阅读:
    GCC内联汇编 Hello
    稳定性调试汇总 Hello
    Logback配置异步输出日志
    Linux查看java进程开启的线程数量
    解决Host key verification failed.
    Linux解压tar.xz文件
    Linux在移动文件到挂载的的SD卡或者镜像时,出现 mv: failed to preserve ownership for ‘***’: Permission denied
    Linux 挂载已有的 img 镜像
    sed命令修改文本内容,可在脚本中使用
    Jmeter 性能测试 Stepping Thread Group 术语解析
  • 原文地址:https://www.cnblogs.com/Mail-maomao/p/11492658.html
Copyright © 2020-2023  润新知