[英]Generics in Swift 2.0
我已經瀏覽了Apple開發者網站上的Swift教程,但我不理解泛型的概念。 有人能夠以簡單的方式解釋它嗎? 例如:
func swapTwoValues<T>(inout a: T, inout b: T) {
let temporaryA = a
a = b
b = temporaryA
}
如果不在您給出的示例中使用泛型,則必須為要交換的每種類型重載swapTwoValues
。 例如:
func swapTwoValues(inout a: Int, inout b: Int) {
let temp = a
a = b
b = temp
}
func swapTwoValues(inout a: String, inout b: String) {
let temp = a
a = b
b = temp
}
// Many more swapTwoValues functions...
上述函數之間唯一不同的是它們接受的類型; 每個內部的代碼完全相同。 因此,最好編寫一個可以采用任何類型的通用函數。
重要的是要注意你不能用Any
替代T
不能保證a
和b
的類型相同 - 例如,你不能交換Int
和String
。
在您的示例中,T表示類型。 並且一旦設置該類型對於整個功能是一致的。
func swapTwoValues<T>(inout a: T, inout b: T) {
let temporaryA = a
a = b
b = temporaryA
}
如果在參數a的情況下T是Int,那么在參數b的情況下它也必須是Int。 正如在這個功能的使用中所證明的:
var valueA = 2
var valueB = 4
swapTwoValues(&valueA, b: &valueB)
valueA // 4
valueB // 2
我們不能為一個Int交換一個String,或者為一個Double交換一個Int,但只要Types相同,那么這個泛型方法將采用任何Type,因為它在所有其他方面都是無限制的。
var valueA = "Hello"
var valueB = "Swift"
swapTwoValues(&valueA, b: &valueB)
valueA // "Swift"
valueB // "Hello"
但是,這並不意味着從通用函數中排除了多種類型。 你只需要指定一個不同的字母來表示不同的類型(使用的字母是無關緊要的,簡單地使用T是因為它是Type的第一個字母,但沒有理由不能用Q替換,例如,或者任何其他信件):
func swapTwoValues<T,S>(inout a: T, inout b: T, inout c: S, inout d: S) {
let temporaryA = a
a = b
b = temporaryA
let temporaryC = c
c = d
d = temporaryC
}
var valueA = 2
var valueB = 4
var valueC = "Hello"
var valueD = "Swift"
swapTwoValues(&valueA, b: &valueB, c:&valueC, d:&valueD)
valueA // 4
valueB // 2
valueC // "Swift"
valueD // "Hello"
注意:我們仍然無法將T替換為S,因為Swift是一種強類型語言,我們無法保證它們是相同的。
當協議涉及約束泛型類型時,它變得更有趣。 這里我使用UnsignedIntegerType:
func swapTwoValues<T: UnsignedIntegerType>(inout a: T, inout b: T) {
let temporaryA = a
a = b
b = temporaryA
}
var valueA:UInt = 10
var valueB:UInt = 11
swapTwoValues(&valueA, b: &valueB)
現在只有UInt,UInt8,UInt32等類型可以接受,所有其他值都將被拒絕並產生錯誤。
注意:使用協議約束類型的原因是可以保證某些方法可以工作。 例如,如果創建新類型實例需要通用函數,則必須采用帶有init方法的協議。 (您可以在Apple的文檔中檢查每種類型的協議采用情況。)
我們可以進一步使用where
關鍵字來確定泛型集合中包含的類型:
func swapTwoValues<T: CollectionType where T.Generator.Element: UnsignedIntegerType>(inout a: T, inout b: T) {
let temporaryA = a
a = b
b = temporaryA
}
var valueA:[UInt] = [10,12,4]
var valueB:[UInt] = [11,45,67]
swapTwoValues(&valueA, b: &valueB)
valueA // [11, 45, 67]
valueB // [10, 12, 4]
或者使用==
檢查第二種類型是否與集合中的Elements類型等效:
func swapTwoValues<T: CollectionType, S where S == T.Generator.Element>(inout a: T, inout b: T, inout c: S, inout d: S) {
let temporaryA = a
a = b
b = temporaryA
let temporaryC = c
c = d
d = temporaryC
}
進一步閱讀: Swift 2中的協議擴展使事情變得更加有趣,因為現在泛型函數可以采用Type方法的特性,這使得它們更容易被發現。
從本質上講,它只是意味着它不是特定於類型的。 您使用T
並只編寫一個函數,而不是為每個類型Int
, Double
, Float
, String
等編寫許多函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.