協議用於統一方法和屬性的名稱,可是協議沒有實現,在其它語言中一般叫作接口。html
使用協議的好處程序員
協議的使用步驟編程
Swift 語言中協議的聲明使用關鍵字 protocol
。swift
protocol 協議: 繼承的協議1, 繼承的協議2 { var 某個屬性: 類型 {set get} func 某個方法(參數列表) -> 返回值類型 init 構造器(參數列表) }
1)在協議中加入的屬性能夠不用實現,也不限制因而計算屬性仍是存儲屬性,可是必需要指出屬性的讀寫權限。數據結構
{set get}
表示可讀寫,{get}
表示可讀。當在實現時爲可讀屬性添加 setter
方法,系統也不會報錯,協議中指定的權限只是最低權限。ide
// 定義協議 protocol someProtocol { var num: Int {get} }
class Show: someProtocol { var so = 1 // 實現協議中定義的屬性 var num: Int { get { return so } set { so = newValue + 1 } } } var show1 = Show() show1.num = 1 print(show1.num) // 2
2)類、結構體和枚舉均可以遵照協議。ui
若是是類遵照了協議,那麼協議中的變異方法和普通方法沒有區別。code
mutating func 變異方法名()
3)能夠在協議的定義中指定某個成員爲類型成員,在成員定義前加上關鍵字 static
便可。htm
protocol someProtocol { // 定義類型成員 static func someTypeNethod() }
4)限制協議僅和類一塊兒工做也是可行的,只須要在冒號後面添加一個 class
關鍵字,這樣就表明這個協議只能被類所遵照。對象
protocol 協議: class, 繼承的協議1, 繼承的協議2 { var 某個屬性: 類型 {set get} func 某個方法(參數列表) -> 返回值類型 init 構造器(參數列表) }
Swift 中遵照協議的格式和繼承父類同樣,把協議名放到類聲明的尾部,在繼承的後面,以逗號隔開。
一個類只能繼承一個父類,可是能夠遵照多個協議。
calss 某個類: 父類, 協議1, 協議2, ... {}
協議別名
若是多個協議老是一塊兒出現,則可使用 typealias
關鍵字給多個協議起一個別名,typealias
並不會生成新的協議。
// Swift 3.0 之前 typealias 協議組合別名 = protocol<協議1, 協議2, ...>
// Swift 3.0 之前 typealias 協議組合別名 = 協議1 & 協議2 ...
calss 某個類: 父類, 協議組合別名 {} struct 某個結構體: 協議組合別名 {}
一旦類遵照了這個協議,就必須實現它裏面的全部成員,否則沒法經過編譯,結構體和枚舉也是如此。
若是類遵照的協議中聲明瞭構造器,那麼遵照協議的類在實現這個構造器的時候必須把構造器聲明爲 required
,不然根據構造器的繼承原則,可能致使子類沒有實現該構造器的狀況。
Swift 2.0 以後蘋果宣稱 Swift 是一門 「面向協議編程」 的語言,這是因爲 Swift 2.0 中引入了對協議擴展的特性。
能夠提早在協議擴展中定義協議的默認實現,不過這些默認實現並不屬於協議自己。
定義兩個協議 Coder 和 Swifter。
protocol Coder { var haveFun: Bool {get} var ownMoney: Bool {get} } protocol Swifter { var codingLevel: Int {get} }
如今有三個公司的程序員,用三個結構體來表示。
struct CoderFromA: Coder { var haveFun: Bool = false var ownMoney: Bool = false var name: String init(name: String) { self.name = name } } struct CoderFromB: Coder, Swifter { var haveFun: Bool = true var ownMoney: Bool = true var codingLevel: Int = 3 var name: String init(name: String) { self.name = name } } struct CoderFromC: Coder, Swifter { var haveFun: Bool = true var ownMoney: Bool = true var codingLevel: Int = 5 var name: String init(name: String) { self.name = name } }
// 使用 let coderA = CoderFromA(name: "A") print("\(coderA.name) - \(coderA.haveFun) - \(coderA.ownMoney)") // A - false - false let coderB = CoderFromB(name: "B") print("\(coderB.name) - \(coderB.haveFun) - \(coderB.ownMoney) - \(coderB.codingLevel)") // B - true - true - 3 let coderC = CoderFromC(name: "C") print("\(coderC.name) - \(coderC.haveFun) - \(coderC.ownMoney) - \(coderC.codingLevel)") // C - true - true - 5
Coder
。觀察上面的代碼能夠發現 Swift 程序員都是快樂且富有的,所以結構體 CoderFromB
和 CoderFromC
中會有冗餘的部分,這是因爲不一樣的協議間的因果關係形成的,雖然咱們知道這個事實,可是因爲規則的關係咱們不得不重複的去賦值 haveFun
和 ownMoney
屬性。
如今使用 swift 的協議擴展,形式以下。
// 定義協議 protocol Coder { var haveFun: Bool {get} var ownMoney: Bool {get} } protocol Swifter { var codingLevel: Int {get} } // 定義協議擴展,設置默認值 extension Coder where Self: Swifter { var haveFun: Bool { return true } var ownMoney: Bool { return true } }
// 定義遵照協議的類型 struct CoderFromA: Coder { var haveFun: Bool = false var ownMoney: Bool = false var name: String init(name: String) { self.name = name } } struct CoderFromB: Coder, Swifter { //var haveFun: Bool = true //var ownMoney: Bool = true var codingLevel: Int = 3 var name: String init(name: String) { self.name = name } } struct CoderFromC: Coder, Swifter { //var haveFun: Bool = true //var ownMoney: Bool = true var codingLevel: Int = 5 var name: String init(name: String) { self.name = name } }
// 使用 let coderA = CoderFromA(name: "A") print("\(coderA.name) - \(coderA.haveFun) - \(coderA.ownMoney)") // A - false - false let coderB = CoderFromB(name: "B") print("\(coderB.name) - \(coderB.haveFun) - \(coderB.ownMoney) - \(coderB.codingLevel)") // B - true - true - 3 let coderC = CoderFromC(name: "C") print("\(coderC.name) - \(coderC.haveFun) - \(coderC.ownMoney) - \(coderC.codingLevel)") // C - true - true - 5
where
限定 Coder
協議的遵照者在同時遵照 Swifter
協議的時候能夠得到本次擴展中的默認實現。Coder
和 Swifter
時,協議 Coder
中的屬性 haveFun
和 ownMoney
會有默認值。haveFun
和 ownMoney
的值以計算屬性 get
方法的形式返回。CoderFromB
和 CoderFromC
中 haveFun
和 ownMoney
的聲明。在協議的擴展中,除了給協議中定義的方法賦上默認實現外,還能夠定義新的方法並賦上默認實現。
1)常規的寫法
// 定義協議 protocol SharedString { func methodForOverride() func methodWithoutOverride() }
// 定義協議擴展,實現方法 extension SharedString { func methodForOverride() { print("method For Override") } func methodWithoutOverride() { methodForOverride() } }
// 使用 extension String: SharedString { } // String 上下文 let str1: String = "Hello" str1.methodForOverride() // method For Override str1.methodWithoutOverride() // method For Override // SharedString 上下文 let str2: SharedString = "Hello" str2.methodForOverride() // method For Override str2.methodWithoutOverride() // method For Override
2)如今在遵照協議的時候從新定義方法 methodForOverride
,修改它的實現。
// 定義協議 protocol SharedString { func methodForOverride() func methodWithoutOverride() }
// 定義協議擴展,實現方法 extension SharedString { func methodForOverride() { print("method For Override") } func methodWithoutOverride() { methodForOverride() } }
// 使用 extension String: SharedString { func methodForOverride() { print(self) } } // String 上下文 let str1: String = "Hello" str1.methodForOverride() // Hello str1.methodWithoutOverride() // Hello // SharedString 上下文 let str2: SharedString = "Hello" str2.methodForOverride() // Hello str2.methodWithoutOverride() // Hello
3)如今把方法 methodWithoutOverride
的聲明從 SharedString
協議列表中刪除,將它變成一個從聲明到實現都在協議擴展中的方法。
// 定義協議 protocol SharedString { func methodForOverride() }
// 定義協議擴展,實現方法 extension SharedString { func methodForOverride() { print("method For Override") } func methodWithoutOverride() { methodForOverride() } }
// 使用 extension String: SharedString { func methodForOverride() { print(self) } } // String 上下文 let str1: String = "Hello" str1.methodForOverride() // Hello str1.methodWithoutOverride() // Hello // SharedString 上下文 let str2: SharedString = "Hello" str2.methodForOverride() // Hello str2.methodWithoutOverride() // Hello
String
和 `SharedString
兩種上下文中調用方法,結果仍舊是同樣的,看起來 String
對協議方法 methodForOverride
的修改是絕對的。4)最後一步,把方法 methodForOverride
從協議列表中列表中刪除,如今 SharedString
的聲明列表是空的了。
// 定義協議 protocol SharedString { }
// 定義協議擴展,實現方法 extension SharedString { func methodForOverride() { print("method For Override") } func methodWithoutOverride() { methodForOverride() } }
// 使用 extension String: SharedString { func methodForOverride() { print(self) } } // String 上下文 let str1: String = "Hello" str1.methodForOverride() // Hello str1.methodWithoutOverride() // method For Override print("\n") // SharedString 上下文 let str2: SharedString = "Hello" str2.methodForOverride() // method For Override str2.methodWithoutOverride() // method For Override
String
時,methodForOverride
會調用被重寫的版本,而未被重寫的方法 methodWithoutOverride
會調用協議擴展中默認的版本,而且未被重寫的方法內部調用協議中其它方法時得到的也是沒有被重寫的版本,這就是協議擴展的 「靜態特性」。SharedString
時,那麼兩個方法都會得到默認的版本。where
的做用是限定協議擴展有效的條件,在 where
語句中可使用 Self
關鍵字來表明協議的遵照者,能夠指定遵照者是某個類的子類或者遵照了某個協議。在 Swift 的協議世界中,每一個對象均可能遵照許多協議,而協議自己能夠做爲一種類型,在使用類型推斷時,編譯器會把對象推斷爲對象自己。
好比說上例中,你能夠經過指定實例的類型修改上下文。
協議自己能夠繼承自另外一個協議,固然不能繼承自另外一個類,由於協議是不能有具體方法實現的,因此不能繼承自類,協議繼承自另外一個協議,無非就是多了一個方法定義。
協議也有繼承關係,若是想要遵照這個協議,就必須把它繼承的協議也所有實現。