Swift 3 協(xié)議(protocol)

協(xié)議,可以理解為一個(gè)類(lèi)型,協(xié)議跟繼承有點(diǎn)像
協(xié)議,就是規(guī)定一個(gè)東西應(yīng)該有那些屬性,有哪些方法
我們可以先定義一個(gè)協(xié)議

protocol Pet{//協(xié)議里邊不能用let
    var name:String {set get}//可讀可寫(xiě)的屬性
    var age:Int {get}
     func playWith()//協(xié)議里邊,只寫(xiě)方法定義
     func init(name:String)//構(gòu)造方法
    func fed(food:String)//不能默認(rèn)值
}

再來(lái)定義一個(gè)類(lèi)(或者結(jié)構(gòu)體等類(lèi)型)來(lái)遵循這個(gè)協(xié)議

class Cat:Pet{
    private var myName:String?//這個(gè)私有變量,是為了寫(xiě)協(xié)議里邊的計(jì)算屬性的set,get方法
    required init(name: String) {
        self.name = name
    }
    //這里,我們用一個(gè)計(jì)算型屬性來(lái)實(shí)現(xiàn)協(xié)議里的name屬性,如果是可讀可寫(xiě)的,我么可以簡(jiǎn)單的寫(xiě)上 var name:String,就和下邊的是等價(jià)的了,如果是get-only的屬性,我們可以let age:Int,就可以了,但是,我們也可以直接用var age:Int,這樣age就是一個(gè)可讀可寫(xiě)的屬性了,這樣是允許的,協(xié)議只規(guī)定了要有一個(gè)age,并且包含get方法就行。這一點(diǎn)很重要
    var name: String{
        set{
            myName = newValue
        }
        get{
        return myName ?? "meiyou"
        }
    }
    func playWith() {
        
    }
    func fed(food: String) {
        
    }
}

這里,協(xié)議里邊的方法,默認(rèn)都是required
如果想有可選方法,可以這樣寫(xiě)

@objc protocol Pet{//協(xié)議里邊不能用let
    var name:String { set get }
    @objc optional func playWith()//可選方法
    func fed(food:String)//不能默認(rèn)值
 }

可以看到在protocol里邊,有一個(gè)構(gòu)造方法,那么,遵循這個(gè)協(xié)議的類(lèi)或者結(jié)構(gòu)體等,都需要重寫(xiě)這個(gè)構(gòu)造方法
在Cat這個(gè)類(lèi)里邊,要這樣

//這里,required表示必須實(shí)現(xiàn),如果Cat還有子類(lèi),那么子類(lèi)也必須寫(xiě)init方法
required init(name: String) {
    }

如果Cat這樣寫(xiě)

final class Cat:Pet{

那么init方法就不需要required了,因?yàn)槲覀円呀?jīng)聲明了這個(gè)類(lèi)不可以被繼承

我們來(lái)提一下泛型
試想一下我們有這么一個(gè)方法,交換兩個(gè)對(duì)象,可以是整型,可以是字符串,可以是Double等等,當(dāng)然我們可以寫(xiě)三個(gè)函數(shù),函數(shù)名是一樣的,只是參數(shù)不一樣,也就是用到函數(shù)的重載,這樣就會(huì)有很多重復(fù)的邏輯,我們可以寫(xiě)一個(gè)這樣的函數(shù)

func exchange<R>(a:inout R, b: inout R){//這里,R是一個(gè)自己定義的,一般我們寫(xiě)的是T,系統(tǒng)也是用的T
    (a,b) = (b,a)//這里利用元組來(lái)實(shí)現(xiàn)交換
}

其實(shí)系統(tǒng)的很多都是泛型類(lèi)型的,典型的有Array, Dictionary,Set等容器類(lèi)型的都是泛型類(lèi)型
我們?cè)賮?lái)說(shuō)一下協(xié)議里邊別名的用法(associatedtype, typealias)

protocol Weight{
    associatedtype weightType//關(guān)聯(lián)一個(gè)類(lèi)型,這里,就相當(dāng)于是定義了一個(gè)類(lèi)型,可以理解為是一個(gè)泛型
    var weight:weightType{ get }
}

用的時(shí)候,可以自定義weightType的類(lèi)型,比如這樣

class iPhone6s:Weight{
    typealias weightType = Double//給協(xié)議里的泛型指定一個(gè)具體類(lèi)型
    var weight: weightType{
        return 123.123
    }
}
let iphone = iPhone6s()
iphone.weight
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容