位置:首頁 > 高級語言 > Swift教學 > Swift泛型類型

Swift泛型類型

泛型類型

通常在泛型函數中,Swift 允許你定義你自己的泛型類型。這些自定義類、結構體和枚舉作用於任何類型,如同ArrayDictionary的用法。

這部分向你展示如何寫一個泛型集類型--Stack(棧)。一個棧是一係列值域的集合,和Array(數組)類似,但其是一個比 Swift 的Array類型更多限製的集合。一個數組可以允許其裡麵任何位置的插入/刪除操作,而棧,隻允許在集合的末端添加新的項(如同push一個新值進棧)。同樣的一個棧也隻能從末端移除項(如同pop一個值出棧)。


注意
棧的概念已被UINavigationController類使用來模擬試圖控製器的導航結構。你通過調用UINavigationControllerpushViewController:animated:方法來為導航棧添加(add)新的試圖控製器;而通過popViewControllerAnimated:的方法來從導航棧中移除(pop)某個試圖控製器。每當你需要一個嚴格的後進先出方式來管理集合,堆棧都是最實用的模型。
 

下圖展示了一個棧的壓棧(push)/出棧(pop)的行為:

此處輸入圖片的描述

  1. 現在有三個值在棧中;
  2. 第四個值“pushed”到棧的頂部;
  3. 現在有四個值在棧中,最近的那個在頂部;
  4. 棧中最頂部的那個項被移除,或稱之為“popped”;
  5. 移除掉一個值後,現在棧又重新隻有三個值。

這裡展示了如何寫一個非泛型版本的棧,Int值型的棧:

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

這個結構體在棧中使用一個Array性質的items存儲值。Stack提供兩個方法:pushpop,從棧中壓進一個值和移除一個值。這些方法標記為可變的,因為它們需要修改(或轉換)結構體的items數組。

上麵所展現的IntStack類型隻能用於Int值,不過,其對於定義一個泛型Stack類(可以處理任何類型值的棧)是非常有用的。

這裡是一個相同代碼的泛型版本:

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

注意到Stack的泛型版本基本上和非泛型版本相同,但是泛型版本的占位類型參數為T代替了實際Int類型。這種類型參數包含在一對尖括號裡(<T>),緊隨在結構體名字後麵。

T定義了一個名為“某種類型T”的節點提供給後來用。這種將來類型可以在結構體的定義裡任何地方表示為“T”。在這種情況下,T在如下三個地方被用作節點:

  • 創建一個名為items的屬性,使用空的T類型值數組對其進行初始化;
  • 指定一個包含一個參數名為itempush方法,該參數必須是T類型;
  • 指定一個pop方法的返回值,該返回值將是一個T類型值。

當創建一個新單例並初始化時, 通過用一對緊隨在類型名後的尖括號裡寫出實際指定棧用到類型,創建一個Stack實例,同創建ArrayDictionary一樣:

var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
stackOfStrings.push("cuatro")
// 現在棧已經有4個string了

下圖將展示stackOfStrings如何push這四個值進棧的過程:

此處輸入圖片的描述

從棧中pop並移除值"cuatro":

let fromTheTop = stackOfStrings.pop()
// fromTheTop is equal to "cuatro", and the stack now contains 3 strings

下圖展示了如何從棧中pop一個值的過程:
此處輸入圖片的描述

由於Stack是泛型類型,所以在 Swift 中其可以用來創建任何有效類型的棧,這種方式如同ArrayDictionary