Optional
是 Swift 重要的语言特性之一,通过引入 Optional
, 可以很好的判断变量是否存在 nil
值的情况,可以很好的防止出现因为未处理 nil
而带来的程序崩溃问题。
下面让我们通过源码来了解一下 Optional 具体的实现逻辑。
Optional
具体的实现是一个包含 .none
和 .some
两个 case 的 enum。
1 | public enum Optional<Wrapped> : ExpressibleByNilLiteral { |
init
由于 Optional 是多类型的,因此我们通过 <Wrapped>
来声明范型。
初始化方法init(_ some:)
可以用来初始化一个非 nil
的实例。 而遵守 ExpressibleByNilLiteral
协议则定义了一个初始化方法init(nilLiteral:)
, 可以使用 nil
初始化一个实例。
map
1 | public func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> U? { |
Optional
类型执行 map
方法时,如果值为 .none
时,直接返回 nil
。如果为 .some(Wrapped)
时,返回 .some(transform(Wrapped))
, 即仍会返回 Optional
类型,仍需进行解包。
可用如下代码验证:1
2
3
4
5
6
7
8
9let possibleNumber: Int? = Int("42")
let possibleSquare = possibleNumber.map { $0 * $0 }
print(possibleSquare)
// "Optional(1764)"
let noNumber: Int? = nil
let noSquare = noNumber.map { $0 * $0 }
print(noSquare)
// "nil"
flatMap
1 | public func flatMap<U>(_ transform: (Wrapped) throws -> U?) rethrows -> U? { |
而在使用 flatMap
时, 如果值为 nil
时,直接返回 nil
, 如果不为 nil
,会进行解包并执行闭包。需要注意的是,transform
时是解包值,但 return
返回的还是 Optional
。
1 | let possibleNumber: Int? = Int("42") |
UnsafelyUnwrapped
1 | public var unsafelyUnwrapped: Wrapped { |
unsafelyUnwrapped
和 强制解包符 !
的功能是相似的,如果为 .none
时会报错。
1 | let possibleNumber: Int? = Int("42") |
Nil Coalescing (??)
1 | public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T) |
上面就是我们在解包时常用的 ??
操作符,它强制要求可能为 nil
的变量放在左边, 默认值写在右边。当 Optional
为 .none
的时候,则返回 defaultValue
的值。
== & !=
1 | public static func ~=(lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool { |
其中重载的一些操作符,用来比较 Optional
类型与 nil
进行, 即我们进行判空时调用的方法。
_ObjectiveCBridgeable
1 | associatedtype _ObjectiveCType : AnyObject |
实现的目的主要用来 Swift 跟 Objective C 中类型进行桥接。Swift 的 Array
和 Dictionary
等遵守这个协议的类型可以转换成OC中对应的 NSArray
和 NSDictionary
类型。
上面就是对 Optional
类型的源码分析,可以看出实现十分巧妙,通过 enum
类型的特性便实现了 Optional
所需要的功能。