您的位置:首页 > 移动开发 > Swift

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

2015-10-13 18:05 423 查看
泛型函数

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

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 = 1
var dog = Animal()
dog.life = 2

swapTwoValues(&cat, &dog)
print(cat.life)  // 2
print(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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: