泛型总的来说有两种使用:泛型函数、泛型类型
// 泛型函数
fun oneBasicGenericityFunction<T>(_ a: inout T, _ b: inout) {
// do something
}
// 泛型类型
struct oneBasicGenericityClass<Element> {
var items = [Element]()
}
在上面的 例子中,占位类型 T ,Element是类型参数的一个例子。类型参数指定并命名一个占位类型,并且紧随在函数名或者类型名后面,使用一对尖括号括起来(例如 <T>,<Element>)。
扩展泛型类型
extension oneBasicGenericityClass {
var topItem: Element? {
return items.isEmpty ? nil : items[items.count - 1]
}
func pirntElements {
for value in items.enumerated {
print(value)
}
}
}
可以看出当你扩展一个泛型类型的时候,你并不需要在扩展的定义中提供类型参数列表。原始类型定义中声明的类型参数列表在扩展中可以直接使用,并且这些来自原始类型中的参数名称会被用作原始定义中类型参数的引用。
类型约束
上面的oneBasicGenericityFunction(::)泛型函数和oneBasicGenericityClass泛型类型中的T,Element可以是任何类型。不过,有的时候如果能将使用在泛型函数和泛型类型中的类型添加一个特定的类型约束,将会是非常有用的。类型约束可以指定一个类型参数必须继承自指定类,或者符合一个特定的协议或协议组合。类型参数的基本语法如下:
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
// 这里是泛型函数的函数体部分
}
在Swift中,class、struct、enums都可以是用参数化类型来表达泛型的,只有在协议中需要使用associatedtype关键字来表达参数化类型。为什么协议不采用这样的语法形式呢? 问题答案传送门
网友评论