Swift学习笔记22——泛型(Generics)

来源:互联网 发布:python opencv hough 编辑:程序博客网 时间:2024/05/29 03:38

泛型函数

当我们写一个函数的时候,一般都会指明参数的类型。比如下面两个实现交换变量的函数(摘自官方文档)

func swapTwoInts(inout a: Int, inout _ b: Int) {    let temporaryA = a    a = b    b = temporaryA}
上面的只是限于交换整形。但是如果我们相对Double或Float类型,甚至是任何类型的数据实现交换的功能,我们都要分别写一个函数。这是无比麻烦的。

所以有了泛型这个概念,泛型就是模糊的类型。当我们函数的功能实现和具体类型没关系的时候,就可以使用泛型。
有了泛型,我们可以将上面实现两个变量交换的功能用一个方法完成,这个方法可以用于不同的数据类型

func swapTwoValues<T>(inout a: T, inout _ b: T) {    let temporaryA = a    a = b    b = temporaryA}
主要的语法就是上面的<T>,这个T就是代表某个类型,但是没有指明具体是哪种类型。而且这个T,可以换成你希望的标示符,只要不是关键字。并且一般要求单词的首字母要大写,比如Element、Value等。而且能指定多个类型,见下面的类型约束

泛型的函数调用方法和普通函数是一样的。下面创建了两个Animal实例,然后使用刚刚定义的函数交换数据。

var cat = Animal()cat.life = 1var dog = Animal()dog.life = 2swapTwoValues(&cat, &dog)print(cat.life)  // 2print(dog.life)  // 1

泛型类型

定义一个类型,但是它可以对不同类型的数据进行操作。比如Array和Dictionary这两个集合结构体,他们可以装不同类型的数据,这就是泛型类型。

官方文档给我们展示了一个泛型类型的栈,它使用Array来实现.

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

然后在创建这种泛型类型实例的时候,我们必须指定所属的类型。

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

泛型约束

我们可以对泛型进行约束,让他们必须遵守某些协议,官方文档语法如下

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

同时还可以添加where约束符再对泛型进行限制

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


关联类型

在定义协议的时候,我们可能需要定义一个或多个类型作为我们协议的一部分。而这些类型是不确定的,只有到具体的类实现协议的时候才能确定,这个时候我们可以使用关联类型来实现。所谓的关联类型就是一个占位符,等到具体实现协议的时候才知道它具体是什么类型。官方例子如下:

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

然后在实现协议的时候,我们可以指定ItemType具体是什么类型

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

同时又因为有Swift的类型判断机制,所以我们在实现了协议的其他方法之后,编译器会自动判断关联类型是什么,不需要我们显式地指定。所以上面代码指定关联类型为Int的那行可以删去。


泛型OC是不支持的,但是java支持。使用泛型能给编程带来很大的便利。


引用文档

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Generics.html#//apple_ref/doc/uid/TP40014097-CH26-ID179



0 0
原创粉丝点击