一.泛型的作用
1. 泛型是一种非常灵活的语法,泛型允许程序在函数、枚举、结构体、类中定义类型形参,这种类型形参实际代表的类型是动态改变的----程序可以等到真正使用这些函数、枚举、结构体时才为这些类型形参传入实际的类型。而且每次使用这些函数、枚举、结构体、类时都可以为泛型的类型形参传入不同的类型。
2. 实例上,Swift的泛型无处不在,许多Swift的标准库都是通过泛型来实现的,比如已经学习过的数组和字典。
3. 如果为了实现某个功能而定义了一个函数,在后期的需求变化中,仍然需要这个函数的功能,但是传入参数的时候参数的类型发生了变化,其他的都没有变。这个时候如果重新再写一个函数,那也只是参数类型不同而已,函数的执行体和之前的函数是完全相同的。如果下次传入的参数变成第三种类型了呢?----解决这个问题的关键就是泛型。
二.泛型函数
1. 泛型函数允许在定义函数指定一个或多个类型占位符,这个类型占位符用于指定函数的一个或多个形参类型或者返回值类型暂时是不确定的,只有等到调用函数时才能确定这些形参类型或返回值类型。
2. 定义泛型函数的语法:
func 函数名 <T, S>(形参列表) ->返回值类型
{
//函数体
}
不难发现,泛型函数的函数签名多了类型占位符(也叫类型形参)声明,类型占位符声明以尖括号括起来,多个占位符之间以逗号分隔,所有的类型占位符声明放在函数名誉形参列表之间。
3. 举个栗子:
func copyArray <T> (src : [T], inout dest : [T])
{
//遍历src数组,并将src数组的元素追加到dest数组后面
for element in src
{
dest.append(element)
}
}
var arr1 = [29, 2, 3]
copyArray([11, 12, 13], &arr1)
var arr2 = ["abc", "def"]
sopyArray(["android", "Swift", "Objective-C"], &arr2)
var arr3 = [1.1, 2.2, 3.3]
copyArray([4.4, 5, 10.1), &arr3)
4. 使用泛型定义多个类型的用法和上面例子中定义一个类型参数的用法相同。
三.泛型类型
1. 泛型不仅可以用在函数中,也可以在Swift的类型(枚举、结构体、类)中使用,使用了泛型的类型就被称为泛型类型。
2. Swift内置支持的Array、Dictionary就是泛型,结构体。
3. 可以为任何类型(包括枚举、结构体、类)增加泛型声明,举个例子:
struct FkRect<T>
{
var x : T
var y : T
var width : T
var height : T
var position : (T, T)
{
return (self.x, self.y)
}
}
let rect1 = FkRect<Double>(x : 1.1, y : 2.2, wdith : 3.3, height : 4.4)
let rect2 = FkRect<Int>(x : 1, y : 2, width : 3, height : 4)
4. 当创建了带泛型声明的父类之后,可以从该父类派生子类。需要指出的是,使用这些父类时不能再包含类型形参。
例如: class Apple<T>
class ABC : Apple<T> ---这样是错误的, Apple类不能跟类型形参
5. 定义函数、枚举、结构体、类时可以声明类型形参,使用函数、枚举、结构体、类时则需要为类型形参传入实例的类型。
6. Swift还要求泛型类的子类必须也带泛型声明,因此如果想从Apple类派生一个子类,则可以这样写:
public class ABC<E> : Apple<String>{}
需要说明的是,E与String并没有任何关系。
7. 扩展泛型类型:扩展泛型类型时,程序并不需要再扩展列表中列出类型形参,扩展体可以直接使用泛型类型多定义的类型形参。举个例子:
class Apple<T>
{
var info : T
init(info : T)
{
self.info = info
}
}
extension Apple
{
func bigThan(other : Apple, fn:(T, T) -> Int) -> Bool{
//....
}
}
var a1 = Apple<String>(info : "apple1")
var a2 = Apple<String>(info : "apple2")
var result = a1.bigThan(a2){
countElements($0) > countElements($1) ? 1 : 0
}
从上面可看出,扩展Apple<T>时无须列出形参列表,但程序在扩展中完全可以使用类型形参T。