Swift 協(xié)議 protocol 小結(jié)

在Swift 2發(fā)布時(shí),蘋(píng)果將Swift定義為一門(mén)面向協(xié)議編程的語(yǔ)言,協(xié)議在Swift中被賦予了更加強(qiáng)大、靈活的功能。相比于Objective-C的協(xié)議,Swift的協(xié)議不僅可以被用做代理,也可以用作對(duì)接口的抽象,代碼的復(fù)用。

1、面向協(xié)議編程

---依賴倒置原則:告訴我們要面向接口編程


定義:高層模塊不應(yīng)該依賴低層模塊,二者都應(yīng)該依賴其抽象;抽象不應(yīng)該依賴細(xì)節(jié);細(xì)節(jié)應(yīng)該依賴抽象。

問(wèn)題由來(lái):類A直接依賴類B,假如要將類A改為依賴類C,則必須通過(guò)修改類A的代碼來(lái)達(dá)成。這種場(chǎng)景下,類A一般是高層模塊,負(fù)責(zé)復(fù)雜的業(yè)務(wù)邏輯;類B和類C是低層模塊,負(fù)責(zé)基本的原子操作;假如修改類A,會(huì)給程序帶來(lái)不必要的風(fēng)險(xiǎn)。

解決方案:將類A修改為依賴接口I,類B和類C各自實(shí)現(xiàn)接口I,類A通過(guò)接口I間接與類B或者類C發(fā)生聯(lián)系,則會(huì)大大降低修改類A的幾率。


2、可選接口

Swift 中的protocol 所有方法都必須被實(shí)現(xiàn),不存在@optional 這樣的概念。為了實(shí)現(xiàn)可選接口有兩個(gè)辦法:(一)@objc 、(二)協(xié)議擴(kuò)展

// 只能被Class實(shí)現(xiàn),struct和enum不可以
@objc protocol StreetSnapTableViewCellDelegate : NSObjectProtocol{
    // 可選
    @objc optional func deleteSeeFewerPhoto(cell : DJStreetSnapTableViewCell, indexPath: IndexPath?)
    func updateCellSubLikeInfoView(cell : DJStreetSnapTableViewCell, indexPath: IndexPath?, likeCount :Int)
    func updateCellSubSimilarsView(cell:UITableViewCell ,indexPath: IndexPath?, selectedIndex : Int)
}

3、協(xié)議擴(kuò)展 protocol extension

// 在Swift2以后,我們可以對(duì)一個(gè)已有的protocol進(jìn)行擴(kuò)展。而擴(kuò)展中實(shí)現(xiàn)的方法作為“實(shí)現(xiàn)擴(kuò)展的類型”的“默認(rèn)實(shí)現(xiàn)
// 通過(guò)提供protocol的extension,我們?yōu)閜rotocol提供了默認(rèn)實(shí)現(xiàn),這相當(dāng)于“變相”將protocol中的方法設(shè)定為了optional

protocol MyProtocol {
    func method()
}

//  默認(rèn)實(shí)現(xiàn) ,代替optional
extension MyProtocol {
    func method() {
        print("Called")
    }
}

struct MyStruct:MyProtocol {

}
MyStruct.method()   //輸出: Called

struct MyStruct:MyProtocol {
    func method() {
        print("Called in struct")
    }
}
MyStruct.method()    //輸出: Called in struct

4、mutating 修飾方法

“Structures and enumerations are value types. By default, the properties of a value type cannot be modified from within its instance methods.”
譯:雖然結(jié)構(gòu)體和枚舉可以定義自己的方法,但是默認(rèn)情況下,實(shí)例方法中是不可以修改值類型的屬性。

protocol Vehicle {
    var wheel: Int {get set}
    // protocol的方法被mutating修飾,才能保證struct和enum實(shí)現(xiàn)時(shí)可以改變屬性的值
    mutating func changeWheel()
}

struct Bike: Vehicle {
    var wheel: Int
    mutating func changeWheel() {
        wheel = 4
    }
}

class Car: Vehicle {
    var wheel: Int = 0
    func changeWheel() {
        wheel = 4
    }
}
var bike = Bike(wheel: 2)
bike.changeWheel()
print(bike.wheel)

let car = Car()
car.changeWheel()
print(car.wheel)

5、static 修飾靜態(tài)方法

protocol Vehicle {
    static func wheel() -> Int
}

struct Bike: Vehicle {
    static func wheel() -> Int {
        return 2
    }
}

// static: protocol、enum、struct 。class:class 
class Car: Vehicle {
    class func wheel() -> Int {
        return 4
    }
}

6、protocol 組合

1、接口隔離原則:利用 Protocol Composition 可以把協(xié)議分得非常細(xì),通過(guò)靈活的組合來(lái)滿足特定要求。
2、「&」這個(gè)操作符可不僅僅能組合協(xié)議而已,也能組合「Type + Protocol」(類型+協(xié)議)。
3、匿名使用:func checkSounds(animal: KittenLike & DogLike)
4、別名:typealias CuteLike = KittenLike & TigerLike & DogLike

// 分工詳細(xì):**接口隔離原則**告訴我們?cè)谠O(shè)計(jì)接口的時(shí)候要精簡(jiǎn)單一
protocol KittenLike {
    func meow() -> String
}

protocol DogLike {
    func bark() -> String
}

protocol TigerLike {
    func aou() -> String
}

// 不推薦
class MysteryAnimal: KittenLike, DogLike, TigerLike {
    func meow() -> String {
        return "meow"
    }
    
    func bark() -> String {
        return "bark"
    }
    
    func aou() -> String {
        return "aou"
    }
}
// 推薦
typealias CuteLike = KittenLike & TigerLike & DogLike
class CuteAnimal: CuteLike {
    func meow() -> String {
        return "meow"
    }
    
    func bark() -> String {
        return "bark"
    }
    
    func aou() -> String {
        return "aou"
    }
}

struct CheckAnimal {
    // 
    static func checkSounds(animal: KittenLike & DogLike) -> Bool {
        return true
    }
}

7、PATs, Protocols with Associated Type

參考:

在協(xié)議中使用范型:

//  Protocols with Associated Types 舉例
struct Model {
    let age: Int
}

//協(xié)議,使用關(guān)聯(lián)類型
protocol TableViewCell {
    associatedtype T
    func updateCell(_ data: T)
}

//遵守TableViewCell
class MyTableViewCell: UITableViewCell, TableViewCell {
    typealias T = Model
    func updateCell(_ data: Model) {
        // do something ...
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 01 舉世皆濁我獨(dú)清,眾人皆醉我獨(dú)醒。 于是屈大夫走在江邊,心力交瘁披發(fā)行吟,嘆楚懷王耳根太軟,受小人挑撥,郁悶異...
    鄭公子vega閱讀 415評(píng)論 1 2
  • 天下熙熙皆為利來(lái),天下攘攘皆為利往。 以前讀到這句話的時(shí)候只覺(jué)得透著一種超脫世俗的清醒,能說(shuō)出這樣話的人一定是個(gè)不...
    張莫默閱讀 220評(píng)論 0 0
  • 這是一個(gè)不知名的國(guó)度的一個(gè)不知名的花園。 這里四季煙霧繚繞,花園里,有著世界上各種各樣的美麗花朵,但,每一種花都只...
    哭腫眼睛充近視閱讀 266評(píng)論 0 1
  • 正如那花 你期待著用心灌溉 總不見(jiàn)花開(kāi) 偶爾路過(guò)的風(fēng)景 卻讓自己心生感慨 生活就是這樣 越追求越離初心漸道漸遠(yuǎn) 缺...
    不惑而歌閱讀 164評(píng)論 0 2
  • 1. ES6 class 注:(1)當(dāng)一個(gè)組件需要調(diào)用Page組件時(shí),只用寫(xiě)成 ,但實(shí)際上解析成了React.cr...
    何幻閱讀 542評(píng)論 0 2

友情鏈接更多精彩內(nèi)容