目录
泛型函数(没有具体的实际类型,会根据使用传入值的类型推导出来)
命名类型参数 (与函数有关系可命名有意义参数, 无关用字符T,U,V
泛型扩展 (添加Extension和实现,类似OC的Cartegory)
关联类型 (associatedType 关键字指定关联类型)
在关联类型约束里使用协议(where 关键字对关联类型约束进行约束)
具有泛型 Where子句的扩展 (extension里用where对类型扩展和约束
具有泛型 Where子句的关联类型(protocol里泛型使用where约束?)
泛型是 Swift 最强大的特性之一,很多 Swift 标准库是基于泛型代码构建的。实际上,即使你没有意识到,你也一直在语言指南中使用泛型。例如,Swift 的 Array
和 Dictionary
都是泛型集合。你可以创建一个 Int
类型数组,也可创建一个 String
类型数组,甚至可以是任意其他 Swift 类型的数组。
泛型解决的问题(不同类型数据进行相同运算的问题?)
// Int 类型的值交换函数
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
// Sting 类型的值交换函数
func swapTwoStrings(_ a: inout String, _ b: inout String) {
let temporaryA = a
a = b
b = temporaryA
}
func swapTwoDoubles(_ a: inout Double, _ b: inout Double) {
let temporaryA = a
a = b
b = temporaryA
}
函数体是一样的,唯一的区别是它们接受的参数类型(Int
、String
和 Double
)
泛型函数(没有具体的实际类型,会根据使用传入值的类型推导出来)
泛型函数和非泛型函数的另外一个不同之处在于这个泛型函数名(swapTwoValues(_:_:)
)后面跟着占位类型名(T
),并用尖括号括起来(<T>
)。这个尖括号告诉 Swift 那个 T
是 swapTwoValues(_:_:)
函数定义内的一个占位类型名,因此 Swift 不会去查找名为 T
的实际类型。T
所代表的类型都会由传入的值的类型推断出来。
// 泛型函数 swapTwoValues(_:_:)
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
泛型版本的函数使用占位符
类型名(这里叫做 T
。通常使用单个字符来表示,例如 T
、U
、V
,例如上面演示函数)
swap(_:_:)
函数存在于 Swift 标准库,你可以在你的应用程序中使用它。
类型参数 ( =占位符
类型名T ?
上面 swapTwoValues(_:_:)
例子中,占位类型 T
是一个类型参数的例子,类型参数指定并命名一个占位类型,并且紧随在函数名后面,使用一对尖括号括起来(例如 <T>
)。
可提供多个类型参数,将它们都写在尖括号中,用逗号分开。<T, U>
命名类型参数 (与函数有关系可命名有意义参数, 无关用字符T,U,V
大多情况下,类型参数具有描述下的名称,例如字典 Dictionary<Key, Value>
中的 Key
和 Value
及数组 Array<Element>
中的 Element
,这能告诉阅读代码的人这些参数类型与泛型类型或函数之间的关系。
当它们之间没有有意义的关系时,通常使用单个字符来表示,例如 T
、U
、V
,
泛型类型(Stack<Element> 栈类型示例)
示例:栈的泛型实现
struct Stack<Element> {
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
}
用占位类型参数 Element
这个类型参数包裹在紧随结构体名的一对尖括号里(<Element
>)。
使用类似于Array 和 Dictionary
泛型扩展 (添加Extension和实现,类似OC的Cartegory)
原始类型定义中声明的类型参数列表在扩展中可以直接使用,并且这些来自原始类型中的参数名称会被用作原始定义中类型参数的引用。
示例:为Stack 扩展 topItem 方法
extension Stack {
Stack 中已有的类型参数名称 Element,被用在扩展中来表示计算型属性 topItem 的可选类型。
var topItem: Element? {
return items.isEmpty ? nil : items[items.count - 1]
}
}
类型约束 (对入参限制为指定类、遵循特定的协议或协议组合
类型约束指定类型参数必须继承自指定类、遵循特定的协议或协议组合。
例如,Swift 的 Dictionary
类型对字典的键的类型做了些限制。在 字典的描述 中,字典键的类型必须是可哈希(hashable)的