接口(interface)


快速入门

type Usb interface {
    // 生成了两个没有实现的方法
    Start()   
    Stop()
}


type Phone struct {

}
func (p Phone) Start{
    fmt.Println("手机开始工作")
}

func (p Phone) Stop{
    fmt.Println("手机停止工作")
}

type Camera struct {
    
}

func (p Camera) Start{
    fmt.Println("相机开始工作")
}

func (p Camera) Stop{
    fmt.Println("相机停止工作")
}

type Coumputer struct {
    
}

// 只要是实现了Usb接口中声明的所有方法,就可以当做变量传到这个方法中
func (c Coumputer) Working(usb Usb){
    usb.Start()
    usb.Stop()
}

func main(){
    cou := Coumputer 
    phone := Phone
    camera := Camera

    cou.Working(phone)
}

基本介绍

interface 类型可以定义一组方法,但是这些都不需要实现,并且interface不能包含任何变量,到某个自定义类型(比如结构体Phone)要使用的时候,再根据传入的参数不同,执行不同方法的interface定义好的方法

  1. 接口中的所有方法都没有方法体,即接口的方法都是没有实现的方法,接口体现了程序设计的多态和高内聚低耦合的思想
  2. Golang中的接口,不需要显式的实现,只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口,因此,Golang中没有implement这样的关键字

基本语法

type 接口名 interface {
    method1(形参列表)(返回值列表)
    method2(形参列表)(返回值列表)
}

应用场景

  1. 想制造轰炸机/武装直升机,专家只需要把飞机需要的功能/规格定下来,然后让别人具体实现即可
  2. 一个项目经理,管理三个程序员,共同开发一个软件,为了控制和管理软件,项目经理可以定义一些接口,然后由程序员具体实现

注意事项和细节

  1. 接口本身是不能创建实例的,但是可以指向一个实现了该接口的自定义类型的变量(实例)

  2. 接口中所有的方法都没有方法体,即都是没有实现的方法

  3. 在Golang中,一个自定义类型需要将某个接口的所有方法都实现,称之为自定义类型实现了该接口,如果只实现了一个方法是不可以的,会报错

  4. 只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型

  5. 一个自定义类型可以实现多个接口

  6. Golang接口中不能有任何变量

  7. 一个接口(比如A接口) 可以继承多个别的接口(比如B,C接口),这时如果要实现A接口,也必须将B,C接口的方法全部实现

  8. interface类型默认是一个指针(引用类型),如果没有对interface初始化就是用,那么会输出nil
    9.空接口interface()没有任何方法,所以所有类型都实现了空接口,即可以把任何变量赋值给空接口类型


接口的最佳实践

实现对Hero结构体切片的排序:sort.Sort(data interface)
用系统函数,对slice切片进行排序
sort.Sort(data interface)
源码(需要实现接口定义的三个方法才可以使用这个方法,进行sort)

type Hero struct{
    Name string
    Age int
}
// 声明一个Hero结构体切片类型
type HeroSlice []Hero

// 实现Interface 接口的三个方法

func (hero HeroSlice) Len() int {
    return len(HeroSlice)
}

// Less 决定使用什么标准进行排序,比如按照Hero的年龄从小到大排序
func (hero HeroSlice) Less(i,j int) bool {
    return hero[i].Age > hero[j].Age  // 根据Age 进行排序
    return hero[i].Name > hero[j].Name // 根据Name 进行排序
}

//Swap 负责交换两个变量的值
func (hero HeroSlice) Swap(i,j int) {
    temp := hero[i]
    hero[i] = hero[j]
    hero[j] = temp
    // 一行代码交换两个变量的值
    hero[i],hero[j] = hero[j],hero[i]
}

func main(){
    // 对数组切片进行排序
    var intslice = []int{0,-1,10,7,90}
    sort.Ints(intslice)
    
    // 对结构体切片进行排序
    var heroes HeroSlice
    for i := 0;i < 10 ;i++{
        hero := Hero{
            Name : fmt.Sprintf("英雄-%d",rand.Intn(100),),
            Age : rand.Intn(100),
        }  
        // 将hero append 到heroes切片
        heroes = append(heroes,hero)
    }

    // 调用sort.Sort
    sort.Sort(heroes)
    
    
    
}

实现接口 VS 继承

  1. 当A结构体继承了B结构体,那么 A 结构体 就集成了B结构体的字段和方法,并且可以直接使用
  2. 当A结构体需要扩展功能,同时不希望破坏继承关系,则可以通过实现某个接口实现
  3. 接口和继承解决的问题不同
    继承的价值主要在于,解决代码的复用性和可维护性
    接口的价值主要在于,设计好各种难规范(方法),让其他自定义类型取实现方法
  4. 接口比继承更灵活,集成式满足is a 的关系,接口只需满足like a 的关系即可
  5. 接口在一定程度上实现了代码解耦


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM