協議基礎

關於協議

協議指定符合協議的 Swift 物件型別(類,結構或列舉)所需的初始化程式,屬性,函式,下標和關聯型別。在某些語言中,後續物件的需求規範的類似想法被稱為介面

宣告和定義的協議是一個型別本身,具有其宣告要求的簽名,有點類似於 Swift 函式是基於其引數和返回的簽名的型別的方式。

Swift 協議規範可以是可選的,明確要求和/或通過稱為協議擴充套件的工具給定預設實現。Swift 物件型別(類,結構或列舉)希望符合使用 Extensions 滿足其所有指定要求的協議,只需說明其符合完全一致性的要求。Protocol Extensions 的預設實現工具足以履行符合協議的所有義務。

協議可以由其他協議繼承。這與 Protocol Extensions 結合使用,意味著 Protocols 可以而且應該被認為是 Swift 的一個重要特性。

協議和擴充套件對於實現 Swift 更廣泛的程式設計靈活性和開發過程的目標和方法非常重要。Swift 的協議和擴充套件功能的主要目的是促程序序架構和開發中的組合設計。這被稱為面向協議的程式設計。堅硬的老計時器認為這優於對 OOP 設計的關注。

協議定義了可以由任何結構列舉實現的介面 :

protocol MyProtocol {
    init(value: Int)                      // required initializer
    func doSomething() -> Bool            // instance method
    var message: String { get }           // instance read-only property
    var value: Int { get set }            // read-write instance property
    subscript(index: Int) -> Int { get }  // instance subscript
    static func instructions() -> String  // static method
    static var max: Int { get }           // static read-only property
    static var total: Int { get set }     // read-write static property
}

協議中定義的屬性必須註釋為 { get }{ get set }{ get } 意味著該屬性必須是 gettable,因此它可以實現為任何型別的屬性。{ get set } 意味著該屬性必須既可以設定也可以獲得。

結構,類或列舉可以符合協議:

struct MyStruct : MyProtocol {
    // Implement the protocol's requirements here
}
class MyClass : MyProtocol {
    // Implement the protocol's requirements here
}
enum MyEnum : MyProtocol {
    case caseA, caseB, caseC
    // Implement the protocol's requirements here
}

協議還可以通過擴充套件來定義其任何需求的預設實現

extension MyProtocol {
    
    // default implementation of doSomething() -> Bool
    // conforming types will use this implementation if they don't define their own
    func doSomething() -> Bool {
        print("do something!")
        return true
    }
}

協議可以用作型別,只要它沒有 associatedtype 要求

func doStuff(object: MyProtocol) {
    // All of MyProtocol's requirements are available on the object
    print(object.message)
    print(object.doSomething())
}

let items : [MyProtocol] = [MyStruct(), MyClass(), MyEnum.caseA]

你還可以定義符合多個協議的抽象型別 :

Version >= 3.0

使用 Swift 3 或更高版本,可以通過使用&符號(&)分離協議列表來完成:

func doStuff(object: MyProtocol & AnotherProtocol) {
    // ...
}

let items : [MyProtocol & AnotherProtocol] = [MyStruct(), MyClass(), MyEnum.caseA]

Version < 3.0

舊版本具有語法 protocol<...>,其中協議是尖括號 <> 之間的逗號分隔列表。

protocol AnotherProtocol {
    func doSomethingElse()
}

func doStuff(object: protocol<MyProtocol, AnotherProtocol>) {
    
    // All of MyProtocol & AnotherProtocol's requirements are available on the object
    print(object.message)
    object.doSomethingElse()
}

// MyStruct, MyClass & MyEnum must now conform to both MyProtocol & AnotherProtocol
let items : [protocol<MyProtocol, AnotherProtocol>] = [MyStruct(), MyClass(), MyEnum.caseA]

可以擴充套件現有型別以符合協議:

extension String : MyProtocol {
    // Implement any requirements which String doesn't already satisfy
}