Swift 提供了泛型让你写出灵活且可重用的函数和类型。
1. 集合类
在Swift的集合类中,元素类型是必须指定的,如果元素类型不同,则需要指定为Any
或AnyObject
。
class Peron {
}
class User {
}
var arr = [Peron]()
arr.append(Peron())
arr.append(User()) // error: Cannot convert value of type 'User' to expected argument type 'Peron'
如果你试图违反指定的泛型进行操作,编译器会报错。
2. 指定参数类型
当我们有一个函数、算法可以运用给多种类型时,在OC中只能指派给父类或id
类型,填参时没关系,但是相关返回值则不是我们所期望的。
Swift泛型则可以完美解决这种问题。
struct Number<T> {
var value: T
init(value: T) {
self.value = value
}
}
let num1 = Number.init(value: 5) // num1.value: Int = 5
let num2 = Number.init(value: 5.5) // num2.value: Double = 5.5
3. 对泛型进行约束
很多时候,我们只会有其中有限的场景进行我们的修改,不想影响到其他的场景,那么我们可以给泛型进行约束。
struct Number<T: Numeric> {
var value: T
init(value: T) {
self.value = value
}
}
let num1 = Number.init(value: 5) // num1.value: Int = 5
let num2 = Number.init(value: 5.5) // num2.value: Double = 5.5
let num3 = Number.init(value: "Apple") // error: Argument type 'String' does not conform to expected type 'Numeric'
上例约束了泛型T
必须实现Numeric
协议,故传入的String
类型会报错,而Int
和Double
则没有受到影响。
我们也可以在扩展中对泛型进行约束,这里对Int
类型的T
进行了扩展,添加了一个log
函数,Double
类型的T
调用会报错。
extension Number where T == Int {
func log() {
print("Int value: \(self.value)")
}
}
num1.log() // Int value: 5
num2.log() // 'Number<Double>' is not convertible to 'Number<Int>'