簡體   English   中英

Swift 2.0中的泛型

[英]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 不能保證ab的類型相同 - 例如,你不能交換IntString

在您的示例中,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並只編寫一個函數,而不是為每個類型IntDoubleFloatString等編寫許多函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM