swift2.2泛型详解

来源:互联网 发布:golang redis集群 编辑:程序博客网 时间:2024/05/03 10:06

Swift2.2范型详解

泛型所解决的问题
泛型函数
类型参数
命名类型参数
泛型类型
扩展一个泛型类型
类型约束
关联类型
Where 子句

1.范型所解决的问题

func swapTwoInts(inout a: Int, inout _ b: Int) {    let temporaryA = a    a = b    b = temporaryA}
func swapTwoStrings(inout a: String, inout _ b: String) {    let temporaryA = a    a = b    b = temporaryA}

上面的swapTwoIntsswapTwoStrings的函数功能是相同的,只是传入函数的参数不同
通常我们需要的是更加灵活的方式来交换两个参数Swift提供了范型范型可以解决这个问题

2.范型函数

func swapTwoValues<T>(inout a: T, inout _ b: T) {    let temporaryA = a    a = b    b = temporaryA}

通过<T>定义一个占位类型,<>表示告诉Swift这里的类型不要去推断T的实际数据类型; 同时后面的传入参数也制定类型为T ,表示传入的参数类型一致,

3.类型参数

在上面的 swapTwoValues(_:_:) 例子中,占位类型 T 是类型参数的一个例子。类型参数指定并命名一个占位类型,并且紧随在函数名后面,使用一对尖括号括起来(例如 <T>)。

一旦一个类型参数被指定,你可以用它来定义一个函数的参数类型(例如 swapTwoValues(_:_:)函数中的参数 ab),或者作为函数的返回类型,还可以用作函数主体中的注释类型。在这些情况下,类型参数会在函数调用时被实际类型所替换。(在上面的 swapTwoValues(_:_:) 例子中,当函数第一次被调用时,TInt 替换,第二次调用时,被 String 替换。)

4.命名类型参数

在大多数情况下,类型参数具有一个描述性名字,例如 Dictionary<Key, Value> 中的 KeyValue,以及 Array<Element> 中的 Element,这可以告诉阅读代码的人这些类型参数和泛型函数之间的关系。然而,当它们之间没有有意义的关系时,通常使用单个字母来命名,例如 TUV,正如上面演示的 swapTwoValues(_:_:) 函数中的 T 一样。

5.泛型类型

除了泛型函数,Swift 还允许你定义泛型类型。这些自定义类、结构体和枚举可以适用于任何类型,类似于 Array 和 Dictionary。
下面定义的是一个泛型类型的结构体

struct Stack<Element> {    var items = [Element]()    mutating func push(item: Element) {        items.append(item)    }    mutating func pop() -> Element {        return items.removeLast()    }}//代码中的mutating :Swift中protocol的功能比OC中强大很多,不仅能再class中实现,同时也适用于struct、enum。使用 mutating 关键字修饰方法是为了能在该方法中修改 struct 或是 enum 的变量,在设计接口的时候,也要考虑到使用者程序的扩展性。所以要多考虑使用mutating来修饰方法。

创建Stack实例 并且加入数据

var stackOfStrings = Stack<String>()stackOfStrings.push("uno")stackOfStrings.push("dos")stackOfStrings.push("tres")stackOfStrings.push("cuatro")

![](/Users/zhangyong/Desktop/stackPushedFourStrings_2x.png
)
通过Name<>这样的方式对泛型类型的定义一个占位的数据类型,来实现对多种数据的类型的处理,从而达到泛型类型的根本,同一个类型处理多种数据类型.

6.扩展一个泛型类型

当你扩展一个泛型类型的时候,你并不需要在扩展的定义中提供类型参数列表。原始类型定义中声明的类型参数列表在扩展中可以直接使用,并且这些来自原始类型中的参数名称会被用作原始定义中类型参数的引用。

extension Stack {    var topItem: Element? {        return items.isEmpty ? nil : items[items.count - 1]    }}if let topItem = stackOfStrings.topItem {    print("The top item on the stack is \(topItem).")}

7.类型约束

swapTwoValues(_:_:) 函数和 Stack 类型可以作用于任何类型。不过,有的时候如果能将使用在泛型函数和泛型类型中的类型添加一个特定的类型约束,将会是非常有用的。类型约束可以指定一个类型参数必须继承自指定类,或者符合一个特定的协议或协议组合。

例如,Swift 的 Dictionary 类型对字典的键的类型做了些限制。在字典的描述中,字典的键的类型必须是可哈希(hashable)的。也就是说,必须有一种方法能够唯一地表示它。Dictionary 的键之所以要是可哈希的,是为了便于检查字典是否已经包含某个特定键的值。若没有这个要求,Dictionary 将无法判断是否可以插入或者替换某个指定键的值,也不能查找到已经存储在字典中的指定键的值。

为了实现这个要求,一个类型约束被强制加到 Dictionary 的键类型上,要求其键类型必须符合 Hashable 协议,这是 Swift 标准库中定义的一个特定协议。所有的 Swift 基本类型(例如 String、Int、Double 和 Bool)默认都是可哈希的。

8.类型约束实践

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

Equatable是Swift标准库中支持==比较的协议,通过这个协议就可以保证泛型参数最后是可以进行==操作的,这样也就对泛型添加了类型约束,使此泛型具有了更加强大的功能

0 0
原创粉丝点击