位置:首頁 > 高級語言 > Swift教學 > Swift可選協議要求

Swift可選協議要求

可選協議要求

可選協議含有可選成員,其遵循者可以選擇是否實現這些成員。在協議中使用@optional關鍵字作為前綴來定義可選成員。

可選協議在調用時使用可選鏈,詳細內容在可選鏈章節中查看。

someOptionalMethod?(someArgument)一樣,你可以在可選方法名稱後加上?來檢查該方法是否被實現。可選方法可選屬性都會返回一個可選值(optional value),當其不可訪問時,?之後語句不會執行,並返回nil


注意: 可選協議隻能在含有@objc前綴的協議中生效。且@objc的協議隻能被遵循。
 

Counter類使用CounterDataSource類型的外部數據源來提供增量值(increment amount),如下所示:

@objc protocol CounterDataSource {
    @optional func incrementForCount(count: Int) -> Int
    @optional var fixedIncrement: Int { get }
}

CounterDataSource含有incrementForCount可選方法fiexdIncrement可選屬性


注意: CounterDataSource中的屬性和方法都是可選的,因此可以在類中聲明但不實現這些成員,儘管技術上允許這樣做,不過最好不要這樣寫。
 

Counter類含有CounterDataSource?類型的可選屬性dataSource,如下所示:

@objc class Counter {
    var count = 0
    var dataSource: CounterDataSource?
    func increment() {
        if let amount = dataSource?.incrementForCount?(count) {
            count += amount
        } else if let amount = dataSource?.fixedIncrement? {
            count += amount
        }
    }
}

count屬性用於存儲當前的值,increment方法用來為count賦值。

increment方法通過可選鏈,嘗試從兩種可選成員中獲取count

  1. 由於dataSource可能為nil,因此在dataSource後邊加上了?標記來表明隻在dataSource非空時才去調用incrementForCount`方法。
  2. 即使dataSource存在,但是也無法保證其是否實現了incrementForCount方法,因此在incrementForCount方法後邊也加有?標記。

在調用incrementForCount方法後,Int可選值通過可選綁定(optional binding)自動拆包並賦值給常量amount

incrementForCount不能被調用時,嘗試使用可選屬性``fixedIncrement來代替。

ThreeSource實現了CounterDataSource協議,如下所示:

class ThreeSource: CounterDataSource {
    let fixedIncrement = 3
}

使用ThreeSource作為數據源開實例化一個Counter

var counter = Counter()
counter.dataSource = ThreeSource()
for _ in 1...4 {
    counter.increment()
    println(counter.count)
}
// 3
// 6
// 9
// 12

TowardsZeroSource實現了CounterDataSource協議中的incrementForCount方法,如下所示:

class TowardsZeroSource: CounterDataSource {
func incrementForCount(count: Int) -> Int {
        if count == 0 {
            return 0
        } else if count < 0 {
            return 1
        } else {
            return -1
        }
    }
}

下邊是執行的代碼:

counter.count = -4
counter.dataSource = TowardsZeroSource()
for _ in 1...5 {
    counter.increment()
    println(counter.count)
}
// -3
// -2
// -1
// 0
// 0