在使用Swift开发的过程中,我们可能经常会碰到泛型。那么究竟什么是泛型?泛型作为Swift最为强大的特性之一,该如何在我们自己的代码中去使用?接下来我们就去详细的了解下什么是泛型,该如何使用泛型。
首先,泛型并不是具体的指某一个类型,而是是一种特性,可以让你根据自己的需求,写出可以支持任意类型的、灵活并且易于复用的函数和类型。
定义泛型函数
使用在函数名后边添加类型参数( <类型参数名>
) 的方式来定义泛型函数,如果有多个这样的类型参数名
使用,
来分割,另外 占位类型
应该使用以大写字母开头的驼峰命名法。
func printPossibleValue<Value>(value: Value) {
print(value)
}
printPossibleValue(value:)
函数可以接受一个任意类型的值,然后把这个值打印出来,这个值可能是Int
,String
,Double
等等类型。<Value>
实际上只是一个类型参数,是一个占位类型,编译器不会去检测是否真的有一个这样的类型声明。
定义泛型类型
struct storedSomething<Something>{
var something: Something
}
除了将结构体定义成泛型,还有可以将自定义类、枚举也定义成泛型类型。
扩展泛型类型
我们可以为一个泛型类型添加扩展(Extension),但不需要我们再为扩展提供类型参数列表。我们可以直接使用原类型定义中的类型参数名。
extension storedSomething{
var otherThing: Something
}
类型约束
当我们希望一个对一个使用在泛型函数或者泛型类型的类型做些限制时,就需要用到类型约束。类型约束可以指定某个类型参数必须继承自某个类,必须遵循某个协议或协议组合。约束的语法为:在某个类型参数名后添加类名或者协议名,两者中间用:
分割
protocol AProtocol {
//statement
}
class BClass {
//statement
}
func someFunction<AType: AProtocol, BType: BClass>(a: AType, b: BType) {
//statement
}
泛型函数 someFunction(a: b:)
包含两个类型参数名分别为AType,BType的类型参数。这个两个类型参数分别遵循AProtocol和继承自BClass,也就是说函数参数a只接受遵循AProtocol的类型,参数b只接受继承自BClass的类型。我们可以用类型约束来限制泛型可接受的类型。
关联类型
前边我们已经知道了如何定义一个泛型类型和泛型函数,但是我们该如何为一个协议添加类似泛型的支持?当我们需要为一个协议添加类似泛型支持时使用关键字associatedType
来指定关联类型。
protocol someProtocol {
associatedtype SomeType
mutating func printItem(item: SomeType)
}
struct someStruct: someProtocol{
typealias SomeType = Int
mutating func printItem(item: Int) {
print(item)
}
}
当我们遵守了SomeProtocol
协议时,意味着我们要去指定 SomeType
具体是什么类型,不过typealias SomeType = Int
并不是必须需要添加的,只要我们指定了函数printItem(item:)
中参数item的类型,swift就会自动推断出SomeType
为Int
类型。
泛型使用 where 语句
除了可以直接为泛型添加约束外,我们还可以使用关键字 where
来为泛型或者关联类型添加额外的条件。where
语句应该写在类型名或者函数返回值之后大括号之前。
protocol someProtocol {
associatedtype SomeType
mutating func printItem(item: SomeType)
}
struct SomeStruct: someProtocol{
typealias SomeType = Int
mutating func printItem(item: Int) {
print(item)
}
}
struct OtherStruct: someProtocol{
mutating func printItem(item: String) {
print(item)
}
}
func doSomething<SomethingA: someProtocol, SomethingB: someProtocol>(a: SomethingA, b: SomethingB) -> Bool where SomethingA.SomeType == SomethingB.SomeType {
print(a,b)
return true
}
let structA = SomeStruct()
let structB = OtherStruct()
doSomething(a: structA, b: structB)//编译器会报一个错误
这段代码中我们使用where
限制了类型参数SomethingA和SomethingB中的关联类型SomeType
的类型必须一致,否则编译器会报错。
网友评论