第二十三章.泛型

来源

 

 

泛型函数

在函数名后面加一个<T>,表示泛型函数,其中T可以是任意的,并且可以支持多个类型参数,命名在尖括号中,用逗号分开。

func swapTwoValues<T>(inout a: T, inout b: T) {
    let temporaryA = a
    a = b
    b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoValues(&someInt, &anotherInt)
// someInt  107, and anotherInt  3

 

泛型类型

下图展示了一个栈的压栈(push)/出栈(pop)的行为:

第二十三章.泛型_第1张图片

 

这里展示了如何写一个非泛型版本的栈,Int值型的栈:

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

泛型版本:

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

 

类型约束

类型约束语法

在一个类型参数名后面的类型约束,通过冒号分割

func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
    // function body goes here
}

上面那个方法要求T是SomeClass类型或是继承自SomeClass。U是SomeProtocol协议,或是实现了SomeProtocol协议

再看一个示例:

func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? {
    for (index, value) in enumerate(array) {
        if value == valueToFind {
            return index
        }
    }
    return nil
}

T 表示一个遵循了Equatable的协议的类型

 

关联类型

关联类型使用typealias关键字。

protocol Container {
    typealias ItemType // 关联类型
    mutating func append(item: ItemType)
    var count: Int { get }
    subscript(i: Int) -> ItemType { get }
}

Container协议定义了三个任何容器必须支持的兼容要求:

  • 必须可能通过append方法添加一个新item到容器里;
  • 必须可能通过使用count属性获取容器里items的数量,并返回一个Int值;
  • 必须可能通过容器的Int索引值下标可以检索到每一个item。

一个非泛型的版本,遵循Container协议

struct IntStack: Container {
    // IntStack的原始实现
    var items = [Int]()
    mutating func push(item: Int) {
        items.append(item)
    }
    mutating func pop() -> Int {
        return items.removeLast()
    }
    // 遵循Container协议的实现
    typealias ItemType = Int
    mutating func append(item: Int) {
        self.push(item)
    }
    var count: Int {
      return items.count
    }
    subscript(i: Int) -> Int {
        return items[i]
    }
}

 

生成遵循Container协议的泛型Stack类型:

struct Stack<T>: Container {
    // original Stack<T> implementation
    var items = [T]()
    mutating func push(item: T) {
        items.append(item)
    }
    mutating func pop() -> T {
        return items.removeLast()
    }
    // conformance to the Container protocol
    mutating func append(item: T) {
        self.push(item)
    }
    var count: Int {
    return items.count
    }
    subscript(i: Int) -> T {
        return items[i]
    }
}

 

扩展一个存在的类型为一指定关联类型

实现一个空扩展的行为:

extension Array: Container {}

定义了这个扩展后,你可以将任何Array当作Container来使用。

 

Where语句

类型约束能够确保类型符合泛型函数或类的定义约束。

func allItemsMatch<
    C1: Container, C2: Container
    where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
    (someContainer: C1, anotherContainer: C2) -> Bool {

        // 检查两个Container的元素个数是否相同
        if someContainer.count != anotherContainer.count {
            return false
        }

        // 检查两个Container相应位置的元素彼此是否相等
        for i in 0..<someContainer.count {
            if someContainer[i] != anotherContainer[i] {
                return false
            }
        }

        // 如果所有元素检查都相同则返回true
        return true

}

这个函数的类型参数列紧随在两个类型参数需求的后面:

  1. C1必须遵循Container协议 (写作 C1: Container)。
  2. C2必须遵循Container协议 (写作 C2: Container)。
  3. C1ItemType同样是C2的ItemType(写作 C1.ItemType == C2.ItemType)。
  4. C1ItemType必须遵循Equatable协议 (写作 C1.ItemType: Equatable)。

第三个和第四个要求被定义为一个where语句的一部分,写在关键字where后面,作为函数类型参数链的一部分。

这些要求意思是:

someContainer是一个C1类型的容器。 anotherContainer是一个C2类型的容器。someContaineranotherContainer包含相同的元素类型。 someContainer中的元素可以通过不等于操作(!=)来检查它们是否彼此不同。

  

下面演示allItemsMatch函数运算的过程:

// 1、创建一个Stack单例来存储String
var stackOfStrings = Stack<String>()
// 2、压了三个字符串进栈 stackOfStrings.push(
"uno") stackOfStrings.push("dos") stackOfStrings.push("tres")
// 3、创建了一个Array单例,并初始化包含三个同栈里一样的原始字符串 var arrayOfStrings
= ["uno", "dos", "tres"]
// 4、调用allItemsMatch函数,用定义的两个Container作为它的参数
if allItemsMatch(stackOfStrings, arrayOfStrings) { println("All items match.") } else { println("Not all items match.") } // 最后输出 "All items match."

 

2015-03-25

20:18:09

你可能感兴趣的:(泛型)