在本章中,你将學會
Generics
泛型的使用方法。
前言
和
Apple
官網或者網上分享的教程類文章不同,我将以實際開發角度講述
Swift
語言的一些概念和用法,友善大家更好地學習和掌握
Swift
語言。
這同時也是對自己學習
Swift
語言過程的知識整理。
如有錯誤,以你為準。
項目建立
我們建立一個
PlayGround
項目,命名為
SwiftGenerics
。
泛型定義
泛型,是一種不确定的資料類型。
泛型允許我們在編寫代碼時使用一些以後才指定的類型,并能在執行個體化時作為參數指明這些類型。
簡單來說,泛型就是一個“
占位符
”,用來代替目前不确定的類型。
泛型函數
泛型函數使用到了一個“
_
”占位類型來代替參數值,進而提高代碼複用率,減少代碼量。示例:
func gotoAppStore(appId: String) {
let urlPrex = "itms-apps"
let appUrl = urlPrex + "://itunes.apple.com/app/id" + appId
let appNsUrl = NSURL(string: appUrl)
UIApplication.shared.open(appNsUrl! as URL, options: [:], completionHandler: nil)
}
gotoAppStore(appId: "App的ID")
上述代碼是我們學習過的通過傳入一個
String
類型的
appId
參數,然後跳轉到
AppStore
的方法。
調用的時候,我們會指定傳入的參數,這裡使用的參數是
appId
。
但如果我們使用泛型函數,就可以不指定參數,泛型可以将類型參數化。示例:
func gotoAppStore(_ appId: String) {
let urlPrex = "itms-apps"
let appUrl = urlPrex + "://itunes.apple.com/app/id" + appId
let appNsUrl = NSURL(string: appUrl)
UIApplication.shared.open(appNsUrl! as URL, options: [:], completionHandler: nil)
}
gotoAppStore("App的ID")
使用泛型函數,我們就不需要指定參數,直接調用方法,達到減少代碼量的效果,這也算是
Apple
官方極度追求代碼優雅的結果。
Swift
标準庫是通過泛型代碼建構出來的,像我們之前學習過的數組、字典其實也都是泛型集合。
泛型類型
除了可以使用泛型函數減少代碼量外,我們還可以自定義泛型類型,如果我們提前不知道需要接受到的資料類型,我們就可以先定義好一個泛型類型,然後确定類型後直接調用方法。示例:
struct Example<ArrayElement> {
var items = [ArrayElement]()
mutating func push(_ item: ArrayElement) {
items.append(item)
}
}
上述代碼中,我們定義了一個自定義類型的結構體
Example
,在
Example
結構體中,我們聲明了一個
items
數組,它也是自定義類型的。
然後寫了一個方法,通過泛型函數的方法傳入參數,将傳入的參數添加到自定義類型的
items
數組中。
我們可以發現,我們在聲明數組時是沒有指定這個數組是什麼類型的,
Example
結構體傳入也是,它就是泛型類型。
這樣在我們在後面确定好傳入的參數類型後,我們就不需要重新修改數組的類型。示例:
var exampleStrings = Example<String>()
exampleStrings.push("文如秋雨")
上述代碼中,我們聲明了一個
exampleStrings
變量,它給
Example
結構體定義了
String
類型,後面我們就可以直接調用
push
傳入相應類型的參數即可。
關聯類型
在我們定義協定時,我們對于協定中的屬性也可以使用到泛型的方法,這裡提及一個關聯屬性的概念,也就是我們在協定中可以先不定義屬性的類型,而在使用的時候再确定屬性的類型。示例:
protocol Person {
associatedtype FullName
mutating func push(_ item: FullName)
}
上述代碼中,我們定義了一個
Person
協定,然後使用
associatedtype
關鍵字聲明了一個還不确定類型的參數
FullName
。
然後依舊寫了一個接收泛型函數的方法
push
,我們再定義一個
class
來遵循這個協定。示例:
class People: Person {
typealias FullName = String
func push(_ item: String) {
print("輸入的FullName是String")
}
}
var exampleStrings2 = People()
exampleStrings2.push("文如秋雨")
上述代碼中,我們定義了一個類
People
,遵循
Person
協定,然後調用
typealias
關鍵字,給
FullName
參數設定了一個關聯類型
String
。
然後在方法中傳入參數,列印輸出文字。
我們可以通過上面的方法知道,使用關聯類型時,我們就不需要在提前設定參數的類型,在我們實際業務中使用到了我們再定義,也就不用老是修改代碼,進而提高代碼複用率,減少代碼量。