Swift 开发新高度:自己动手实现 Optional 类型
这里每天分享一个 iOS 的新知识,快来关注我吧
前言
对于熟悉 Swift 开发的同学一定对 Optional 类型不陌生,它是 Swift 中一个强大的特性,它通过显式处理有值或无值(nil)帮助我们编写更安全的代码。
Swift 提供了对 Optionals
的内置支持,今天来讲讲如何实现一个自定义的 Optionals
类型。
定义我们的自定义 Optional
首先我们来看看官方 Optional 这个类型的声明:
public enum Optional<Wrapped> : ExpressibleByNilLiteral {
case none
case some(Wrapped)
}
这段代码声明在 Swift.Optional 中,可以看出一些信息:
-
它实际上是个枚举(enum)
-
它声明了一个泛型 Wrapped,做为 some 的关联值
-
它有两个 case,none 和 some
那么,我们按着官方的代码也使用 enum
来定义我们的自定义 Optional 类型:
enum CustomOptional<Wrapped> {
case some(Wrapped)
case none
}
这个枚举同样也有两个 case :some
包含一个关联值,表示包装的类型;none
表示值的缺失(nil)。泛型 <Wrapped>
允许我们的 CustomOptional
适用于任何类型。
访问和解包值
接下来,我们添加一些方法来访问和解包值:
extension CustomOptional {
// MARK: - 访问和解包
var value: Wrapped? {
switch self {
case .some(let wrapped): // 有值
return wrapped
case .none: // 无值
return nil
}
}
// 解包
func unwrap() throws -> Wrapped {
switch self {
case .some(let wrapped): // 有值
return wrapped
case .none: // 无值
// 抛出一个错误
throw CustomOptionalError.unwrappingNone
}
}
enum CustomOptionalError: Error {
case unwrappingNone // 无值,无法解包
}
}
简单解释一下这段代码,我们添加了一个 value
属性和一个 unwrap()
方法:
value
属性:返回包装的值,如果是 none
则返回 nil
。unwrap()
方法:强制解包值,如果是 none
则抛出一个错误。
实现可选链
我们可以实现 map
和 flatMap
的简化版本来支持可选链:
extension CustomOptional {
// MARK: - 可选链
// map,如果包装的值存在,则使用提供的转换闭包来转换值
func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> CustomOptional<U> {
switch self {
case .some(let wrapped): // 有值转换
return .some(try transform(wrapped))
case .none: // 无值返回 none
return .none
}
}
func flatMap<U>(_ transform: (Wrapped) throws -> CustomOptional<U>) rethrows -> CustomOptional<U> {
switch self {
case .some(let wrapped):
return try transform(wrapped) // 有值转换
case .none:
return .none // 无值返回 none
}
}
}
map
和 flatMap
:这些方法提供了可选链的简化版本:
-
map
:如果包装的值存在,则使用提供的转换闭包来转换值。 -
flatMap
:跟map
类似,区别在于转换闭包返回的是一个CustomOptional
类型。
将我们的自定义 Optional 使用起来
现在我们可以使用我们的 CustomOptional
类型了:
let someValue: CustomOptional<Int> = .some(42)
let noValue: CustomOptional<Int> = .none
// 访问值
print(someValue.value) // Optional(42)
print(noValue.value) // nil
// 解包
do {
let unwrapped = try someValue.unwrap()
print(unwrapped) // 42
} catch {
print("Error unwrapping: \(error)")
}
// 可选链
let doubled = someValue.map { $0 * 2 }
print(doubled.value) // Optional(84)
let stringified = someValue.flatMap { value in
CustomOptional<String>.some(String(value))
}
print(stringified.value) // Optional("42")
实现我们的 CustomOptional
类型可以深入了解 Swift 的 Optionals
在底层大概是如何实现的。虽然这个实现并不包括 Swift 内置 Optionals
的所有特性(比如 ??
操作符或隐式解包),但它涵盖了核心功能,并展示了 Swift 中代数数据类型的强大力量。
希望这篇文章对你理解 Swift 的 Optionals
有所帮助,如果你有任何问题或建议,欢迎在评论区告诉我们!
这里每天分享一个 iOS 的新知识,快来关注我吧
本文同步自微信公众号 “iOS新知”,每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!