位置:首頁 > 高級語言 > Swift教學 > Swift Where語句

Swift Where語句

Where 語句

類型約束中描述的類型約束確保你定義關於類型參數的需求和一泛型函數或類型有關聯。

對於關聯類型的定義需求也是非常有用的。你可以通過這樣去定義where語句作為一個類型參數隊列的一部分。一個where語句使你能夠要求一個關聯類型遵循一個特定的協議,以及(或)那個特定的類型參數和關聯類型可以是相同的。你可寫一個where語句,通過緊隨放置where關鍵字在類型參數隊列後麵,其後跟著一個或者多個針對關聯類型的約束,以及(或)一個或多個類型和關聯類型的等於關係。

下麵的列子定義了一個名為allItemsMatch的泛型函數,用來檢查是否兩個Container單例包含具有相同順序的相同元素。如果匹配到所有的元素,那麼返回一個為trueBoolean值,反之,則相反。

這兩個容器可以被檢查出是否是相同類型的容器(雖然它們可以是),但它們確實擁有相同類型的元素。這個需求通過一個類型約束和where語句結合來表示:

func allItemsMatch<
    C1: Container, C2: Container
    where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
    (someContainer: C1, anotherContainer: C2) -> Bool {

        // check that both containers contain the same number of items
        if someContainer.count != anotherContainer.count {
            return false
        }

        // check each pair of items to see if they are equivalent
        for i in 0..someContainer.count {
            if someContainer[i] != anotherContainer[i] {
                return false
            }
        }

        // all items match, so return true
        return true

}

這個函數用了兩個參數:someContaineranotherContainersomeContainer參數是類型C1anotherContainer參數是類型C2C1C2是容器的兩個占位類型參數,決定了這個函數何時被調用。

這個函數的類型參數列緊隨在兩個類型參數需求的後麵:

  • C1必須遵循Container協議 (寫作 C1: Container)。
  • C2必須遵循Container協議 (寫作 C2: Container)。
  • C1ItemType同樣是C2的ItemType(寫作 C1.ItemType == C2.ItemType)。
  • C1ItemType必須遵循Equatable協議 (寫作 C1.ItemType: Equatable)。

第三個和第四個要求被定義為一個where語句的一部分,寫在關鍵字where後麵,作為函數類型參數鏈的一部分。

這些要求意思是:

someContainer是一個C1類型的容器。 anotherContainer是一個C2類型的容器。 someContaineranotherContainer包含相同的元素類型。 someContainer中的元素可以通過不等於操作(!=)來檢查它們是否彼此不同。

第三個和第四個要求結合起來的意思是anotherContainer中的元素也可以通過 != 操作來檢查,因為它們在someContainer中元素確實是相同的類型。

這些要求能夠使allItemsMatch函數比較兩個容器,即便它們是不同的容器類型。

allItemsMatch首先檢查兩個容器是否擁有同樣數目的items,如果它們的元素數目不同,冇有辦法進行匹配,函數就會false

檢查完之後,函數通過for-in循環和半閉區間操作(..)來迭代someContainer中的所有元素。對於每個元素,函數檢查是否someContainer中的元素不等於對應的anotherContainer中的元素,如果這兩個元素不等,則這兩個容器不匹配,返回false

如果循環體結束後未發現冇有任何的不匹配,那表明兩個容器匹配,函數返回true

這裡演示了allItemsMatch函數運算的過程:

var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")

var arrayOfStrings = ["uno", "dos", "tres"]

if allItemsMatch(stackOfStrings, arrayOfStrings) {
    println("All items match.")
} else {
    println("Not all items match.")
}
// 輸出 "All items match."

上麵的例子創建一個Stack單例來存儲String,然後壓了三個字符串進棧。這個例子也創建了一個Array單例,並初始化包含三個同棧裡一樣的原始字符串。即便棧和數組否是不同的類型,但它們都遵循Container協議,而且它們都包含同樣的類型值。你因此可以調用allItemsMatch函數,用這兩個容器作為它的參數。在上麵的例子中,allItemsMatch函數正確的顯示了所有的這兩個容器的items匹配。