接口(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