OneDayOneSwift[23] - Generics

泛型是 Swift 的強大特性之一,許多 Swift 標準庫是通過泛型代碼構建的。事實上,泛型的使用貫穿了整本語言手冊,只是你可能沒有發(fā)現(xiàn)而已。例如,Swift 的 ArrayDictionary 都是泛型集合。

泛型函數(shù)

func swapTwoValues<T>(inout a: T, inout _ b: T) {
    let temporaryA = a
    a = b
    b = temporaryA
}

在大多數(shù)情況下,類型參數(shù)具有一個描述性名字,例如 Dictionary<Key, Value> 中的 KeyValue,以及 Array<Element> 中的 Element,這可以告訴閱讀代碼的人這些類型參數(shù)和泛型函數(shù)之間的關系。然而,當它們之間的關系沒有意義時,通常使用單一的字母來命名,例如 T、UV,正如上面演示的 swapTwoValues(_:_:) 函數(shù)中的 T 一樣。

ps: 請始終使用大寫字母開頭的駝峰式命名法(例如 TMyTypeParameter)來為類型參數(shù)命名,以表明它們是占位類型,而不是一個值。

--對于代碼命名規(guī)則來說,個人感覺此處很關鍵。所以下面把原版也搬過來

Always give type parameters upper camel case names(such as T and MyTypeParameter) to indicate that they are a placeholder for a type,not a value.

泛型類型

除了泛型函數(shù),Swift 還允許你定義泛型類型。這些自定義類、結構體和枚舉可以適用于任何類型,如同 ArrayDictionary 的用法。

struct Stack<Element> {
    var items = [Element]()
    mutating func push(item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
}

擴展一個泛型類型

當你擴展一個泛型類型的時候,你并不需要在擴展的定義中提供類型參數(shù)列表。更加方便的是,原始類型定義中聲明的類型參數(shù)列表在擴展中可以直接使用,并且這些來自原始類型中的參數(shù)名稱會被用作原始定義中類型參數(shù)的引用。

extension Stack {
    var topItem: Element? {
        return items.isEmpty ? nil : items[items.count - 1]
    }
}

類型約束

swapTwoValues(::) 函數(shù)和 Stack 類型可以作用于任何類型。不過,有的時候如果能將使用在泛型函數(shù)和泛型類型中的類型,強制約束為某種特定類型,將會是非常有用的。類型約束可以指定一個類型參數(shù)必須繼承自指定類,或者符合一個特定的協(xié)議或協(xié)議組合。

func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
    // 這里是泛型函數(shù)的函數(shù)體部分
}

關聯(lián)類型

定義一個協(xié)議時,有的時候聲明一個或多個關聯(lián)類型作為協(xié)議定義的一部分將會非常有用。關聯(lián)類型作為協(xié)議的一部分,為某個類型提供了一個占位名(或者說別名),其代表的實際類型在協(xié)議被采納時才會被指定。你可以通過 typealias 關鍵字來指定關聯(lián)類型。

protocol Container {
    typealias ItemType
    mutating func append(item: ItemType)
    var count: Int { get }
    subscript(i: Int) -> ItemType { get }
}

struct IntStack: Container {
    // IntStack 的原始實現(xiàn)部分
    var items = [Int]()
    mutating func push(item: Int) {
        items.append(item)
    }
    mutating func pop() -> Int {
        return items.removeLast()
    }
    // Container 協(xié)議的實現(xiàn)部分
    typealias ItemType = Int
    mutating func append(item: Int) {
        self.push(item)
    }
    var count: Int {
        return items.count
    }
    subscript(i: Int) -> Int {
        return items[i]
    }
}

Where 子句

類型約束讓你能夠為泛型函數(shù)或泛型類型的類型參數(shù)定義一些強制要求。

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

        // 檢查兩個容器含有相同數(shù)量的元素
        if someContainer.count != anotherContainer.count {
            return false
        }

        // 檢查每一對元素是否相等
        for i in 0..<someContainer.count {
            if someContainer[i] != anotherContainer[i] {
                return false
            }
        }

        // 所有元素都匹配,返回 true
        return true
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 4,171評論 1 10
  • 泛型(Generics) 泛型代碼允許你定義適用于任何類型的,符合你設置的要求的,靈活且可重用的 函數(shù)和類型。泛型...
    果啤閱讀 758評論 0 0
  • 136.泛型 泛型代碼讓你可以寫出靈活,可重用的函數(shù)和類型,它們可以使用任何類型,受你定義的需求的約束。你可以寫出...
    無灃閱讀 1,655評論 0 4
  • 本章將會介紹 泛型所解決的問題泛型函數(shù)類型參數(shù)命名類型參數(shù)泛型類型擴展一個泛型類型類型約束關聯(lián)類型泛型 Where...
    寒橋閱讀 713評論 0 2
  • 遙望天上的明月 想象著一個故事的凄惋 詩會讓人兒團圓 直到嫦娥重返人間 童年沒有災難 繁多的作業(yè)是我的玩伴 白天來...
    蕭蕭晚風閱讀 259評論 1 2

友情鏈接更多精彩內容