一、可选类型
1. 定义
可选类型用来表示可能为空的情况,比如这样:
var a: Int? = nil
a = 3
print(a)
/* 执行结果
Optional(3)
Program ended with exit code: 0
*/
从执行结果上可以看到a的值是Optional(3),而非3。那么Optional的本质是什么?
2. 本质
这里我们直接在源码中查看Optional.swift:
从这里可以看出Optional的本质就是枚举,初始化一个可选类型时,如果是nil就是创建Optional.none,否则就创建Optional.some的关联值。其实查看源码我们还可以看到一些运算符重载的方法,比如常见的可选类型取值方式let b = a ?? 0中的空合并运算符??在源码中它是这样的:
从这里可以看到??其实就是对枚举值进行模式匹配。除了运算符重载,还可以看到高阶函数相关的方法:
从这里可以看出高阶函数其实都是先对枚举值进行模式匹配,none就不处理,some则执行闭包。接下来我们参照源码,仿写一个简单的可选类型。
二、仿写可选类型
1. 案例代码
这里我们直接添加代码:
import Foundation
enum MyOptional<T> {
case none
case some(T)
init(_ value: T) {
self = .some(value)
}
init() {
self = .none
}
}
var a: MyOptional<Int> = MyOptional()
a = MyOptional(3)
print(a)
/* 执行结果
some(3)
Program ended with exit code: 0
*/
这就是简单的可选类型,接下来我们给它增加个类似空合并运算符的效果。
2. 运算符重载
这里直接在拓展中添加代码:
import Foundation
enum MyOptional<T> {
case none
case some(T)
init(_ value: T) {
self = .some(value)
}
init() {
self = .none
}
}
extension MyOptional {
/// 运算符重载
static func ?? (lhs: Self, rhs: T) -> T {
switch lhs {
case .none:
return rhs
case let .some(T):
return T
}
}
}
var a: MyOptional<Int> = MyOptional()
a = MyOptional(3)
print(a ?? 0)
/* 执行结果
3
Program ended with exit code: 0
*/
这里可以看到,运算符重载后空合并运算符的效果就有了。
三、总结
可选类型在Swift中使用频率非常高,虽然解包需要通过模式匹配稍微影响了性能,但它给应用加了一层保险。合理运用可选类型,可以有效避免因为nil导致的异常问题。