Arrays
雖然原來的Keeper類型說明了泛型類型不需要存儲任何內(nèi)容或使用它的類型參數(shù)逻淌,但泛型類型的最常見就是同時具有這兩種功能。這就是Array類型猪勇。
使用泛型數(shù)組是發(fā)明泛型類型的原始動機的一部分产禾。由于許多程序需要相同類型的數(shù)組,所以泛型數(shù)組使代碼更安全攒菠。
你一直在使用數(shù)組,但是只有[Element]的預防歉闰,而不是Array<Element>. 思考一個這樣的數(shù)組:
let animalAges: [Int] = [2,5,7,9]
這相當于下面這個數(shù)組:
let animalAges: Array<Int> = [2,5,7,9]
Array<Int>和[Int]是完全可互換的辖众。你甚至可以通過[Int]()
而不是Array <Int>()來調(diào)用數(shù)組的默認初始化方法。
由于Swift數(shù)組只允許對元素序列進行索引訪問和敬,所以它們對元素類型沒有要求凹炸。但情況并非總是如此。
Dictionaries
Swift泛型允許多個類型參數(shù)和對它們的一系列復雜的限制昼弟。它們允許你使用具有關聯(lián)類型的泛型類型和協(xié)議來建立復雜的算法和數(shù)據(jù)結構啤它。字典就是一個簡單的例子。
Dictionary在逗號分隔的泛型參數(shù)列表中有兩個類型參數(shù)舱痘,它們位于尖括號之間变骡,您可以在它的聲明中看到:
struct Dictionary<Key: Hashable, Value> // etc..
Key和Value表示字典的鍵和值的類型。但是Key上的注釋芭逝,Key: Hashable表示的意義很多塌碌。冒號之后的所有內(nèi)容都是類型約束。類型約束指明了該類型參數(shù)父類型旬盯,以及所需的協(xié)議或協(xié)議列表台妆。
例如,Dictionary的類型約束要求作為Dictionary鍵的任何類型都是hashable胖翰,因為Dictionary是一個散列映射频丘,必須對其鍵進行散列,以啟用快速查找泡态。
要實例化具有多個類型參數(shù)的類型(如Dictionary),只需提供一個逗號分隔的類型參數(shù)列表:
let intNames: Dictionary<Int, String> = [42: "forty-two"]
與數(shù)組一樣迂卢,字典在Swift中也有一些特殊的處理某弦,因為它們是內(nèi)置的桐汤,而且非常常見。你已經(jīng)見過速記表示法[Key: Value]靶壮,還可以使用類型推斷:
let intNames2: [Int: String] = [42: "forty-two", 7: "seven"]
let intNames3 = [42: "forty-two", 7: "seven"]
Optionals
最后怔毛,對泛型的討論如果不提及Optionals,就不完整腾降。Optionals通過枚舉實現(xiàn)拣度,但它們也是另一種泛型類型,你可以自己定義它螃壤。
假設你正在編寫一個應用程序抗果,該應用程序允許用戶以表單的形式輸入她的生日,但不是必須的奸晴。你可能會發(fā)現(xiàn)定義enum類型很方便冤馏,如下所示:
enum OptionalDate {
case none
case some(Date)
}
類似地,如果另一個表單不要求用戶輸入她的姓寄啼,你可以定義以下類型:
enum OptionalString {
case none
case some(String)
}
然后逮光,你可以捕獲用戶所輸入或未輸入的所有信息:
struct FormResults {
// other properties here
var birthday: OptionalDate
var lastName: OptionalString
}
如果你發(fā)現(xiàn)新類型在重復做這些,那么你會想把它歸納成一個泛型類型來表示“可能存在的特定類型的值”的概念墩划。因此涕刚,你可以這樣寫:
enum Optional<Wrapped> {
case none
case some(Wrapped)
}
此時,你將復制Swift自己的Optional < Wrapped >類型乙帮,因為這與Swift標準庫中的定義非常接近!事實證明杜漠,Optional < Wrapped >接近于一個普通的舊泛型類型,就像你自己編寫的類型一樣蚣旱。
只有當你與Optional進行交互時碑幅,它才會是一個泛型類型,比如:
var birthdate: Optional<Date> = .none
if birthdate == .none {
// no birthdate
}
但是塞绿,當然沟涨,下面這樣的更常見也更傳統(tǒng):
var birthdate: Date? = nil
if birthdate == nil {
// no birthdate
}
實際上,這兩個代碼塊的含義完全相同异吻。
與數(shù)組和字典一樣裹赴,optionals在語言中具有這種語法的特權地位,使使用它們更簡潔诀浪。但是所有這些特性都提供了訪問底層類型的更方便的方法棋返,這只是一個普通的枚舉類型。
泛型函數(shù)參數(shù)
到目前為止雷猪,你已經(jīng)了解了泛型類型在函數(shù)睛竣、類、結構和枚舉中的定義求摇。除了Dictionary之外射沟,所有這些都有一個通用參數(shù)殊者。
泛型類型參數(shù)列表位于類型名或函數(shù)名之后。然后可以在定義的其余部分中使用泛型參數(shù)验夯。
這個函數(shù)接受兩個參數(shù)并交換它們的順序:
func swapped<T, U>(_ x: T, _ y: U) -> (U, T) {
return (y, x)
}
swapped(33, "Jay") // returns ("Jay", 33)
泛型函數(shù)定義展示了語法的一個令人困惑的方面:它同時具有類型參數(shù)和函數(shù)參數(shù)猖吴。您擁有類型參數(shù)<T、U>的通用參數(shù)列表和函數(shù)參數(shù)列表(_ x: T挥转、_ y: U)海蔽。