Swift:18 協議
協議中可以定義一些方法、屬性以供類、結構體或枚舉遵循。除了遵循協議的類型必須實現的要求外,還可以對協議進行擴展,通過擴展來實現一部分要求或者實現一些附加功能,這樣遵循協議的類型就能夠使用這些功能。
協議語法
協議的定義方式與類、結構體和枚舉的定義非常相似,使用關鍵字protocol來定義協議。要讓自定義類型遵循某個協議,在定義類型時,需要在類型名稱后加上協議名稱,中間以冒號(:)分隔。遵循多個協議時,各協議之間用逗號(,)。如果該類型有父類,則父類需要寫在協議的前面。
protocol FirstProtocol {
// 這里是協議的定義部分
}
protocol SecondProtocol {
// 這里是協議的定義部分
}
class SuperClass{
}
class SomeClass:SuperClass,FirstProtocol,SecondProtocol{
}
屬性要求
協議可以要求遵循協議的類型提供特定名稱和類型的實例屬性或類型屬性。協議不指定屬性是存儲型屬性還是計算型屬性,它只指定屬性的名稱和類型。此外,協議還指定屬性是可讀的還是可讀可寫的。
如果協議要求屬性是可讀可寫的,那么該屬性不能是常量屬性或只讀的計算型屬性。如果協議只要求屬性是可讀的,那么該屬性不僅可以是可讀的,如果代碼需要的話,還可以是可寫的。
//指定實例屬性
protocol SomeProtocol {
var mustBeSettable: Int { get set }
var doesNotNeedToBeSettable: Int { get }
}
//指定類型屬性
protocol AnotherProtocol {
static var someTypeProperty: Int { get set }
}
方法要求
協議可以要求遵循協議的類型實現某些指定的實例方法或類方法。這些方法作為協議的一部分,像普通方法一樣放在協議的定義中,但是不需要大括號和方法體??梢栽趨f議中定義具有可變參數的方法,和普通方法的定義方式相同。但是,不支持為協議中的方法的參數提供默認值。
//類型方法
protocol SomeProtocol {
static func someTypeMethod()
}
//實例方法
protocol RandomNumberGenerator {
func random() -> Double
}
Mutating方法要求
如果你在協議中定義了一個實例方法,該方法會改變遵循該協議的類型的實例,那么在定義協議時需要在方法前加mutating關鍵字。這使得結構體和枚舉能夠遵循此協議并滿足此方法要求。
protocol Togglable {
mutating func toggle()
}
enum OnOffSwitch: Togglable {
case off, on
mutating func toggle() {
switch self {
case .off:
self = .on
case .on:
self = .off
}
}
}
var lightSwitch = OnOffSwitch.off
lightSwitch.toggle()
// lightSwitch 現在的值為 .On
構造器要求在類中的實現
你可以在遵循協議的類中實現構造器,無論是作為指定構造器,還是作為便捷構造器。無論哪種情況,你都必須為構造器實現標上 required 修飾符。使用 required 修飾符可以確保所有子類也必須提供此構造器實現,從而也能符合協議。
protocol SomeProtocol {
init()
}
class SomeSuperClass {
init() {
// 這里是構造器的實現部分
}
}
class SomeSubClass: SomeSuperClass, SomeProtocol {
// 因為遵循協議,需要加上 required
// 因為繼承自父類,需要加上 override
required override init() {
// 這里是構造器的實現部分
}
}
協議擴展
協議可以通過擴展來為遵循協議的類型提供屬性、方法以及下標的實現。通過這種方式,你可以基于協議本身來實現這些功能,而無需在每個遵循協議的類型中都重復同樣的實現,也無需使用全局函數。
protocol RandomNumberGenerator {
func random() -> Double
}
class LinearCongruentialGenerator: RandomNumberGenerator {
var lastRandom = 42.0
let m = 139968.0
let a = 3877.0
let c = 29573.0
func random() -> Double {
lastRandom = ((lastRandom * a + c).truncatingRemainder(dividingBy:m))
return lastRandom / m
}
}
extension RandomNumberGenerator {
func randomBool() -> Bool {
return random() > 0.5
}
}
let generator:RandomNumberGenerator = LinearCongruentialGenerator()
print("生成一個隨機數: \(generator.random())")
print("再生成一個隨機數: \(generator.random())")
print("生成一個隨機布爾值: \(generator.randomBool())")
``
代碼執行結果如下圖所示。
<img src="http://qiniu.99ios.com/99ios/1486721587524.png" width="593"/>
# 示例代碼
<https://github.com/99ios/23.19>
---