swift 可选值详解

114 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第25天,点击查看活动详情

Optional

认识可选值

之前我们在写代码的过程中早就接触过可选值,比如我们在代码这样定义:

class ZGTeacher {
    var age: Int?
}

当前的 age 我们就称之为可选值,那对于 Optional 的本质是什么?我们直接跳转到源码,打开 Optional.swift 文件。

public enum Optional<Wrapped>: ExpressibleByNilLiteral {
  
  case none

  case some(Wrapped)
}

从源码可以得知,Optional 的本质是枚举,那么我们也可以仿照系统的实现制作一个自己的 Optional。

比如给定任意一个自然数,如果当前自然数是偶数返回,否则为 nil,我们应该怎么表达这个案例。

enum MyOptional<Value> {
    case none
    case some(Value)
}

func getOddValue(_ value: Int) -> MyOptional<Int> {
    if value % 2 == 0 {
        return .some(value)
    } else {
        return .none
    }
}

这个时候给定一个数组,我们想删除数组中所有的偶数

image.png

这个时候编译器就会检查我们当前的 value 会发现他的类型和系统编译器期望的类型不符,这 个时候我们就能使用 **MyOptional**来限制语法的安全性。

于此同时我们通过 enum 的模式匹配来取出对应的值。

for index in array {
    let value = getOddValue(index)
    switch value {

    case .some(let v):
        array.remove(at: array.firstIndex(of: v)!)
    case .none :
        print("value not exit")
    }
}

如果我们把上述的返回值更换一下,其实就和系统的 **Optional**使用无疑。

func getOddValue(_ value: Int) -> Int {
    if value % 2 == 0 {
        return .some(value)
    } else {
        return .none
    }
}

这样我们其实是利用当前编译器的类型检查来达到语法书写层面的安全性。

当然如果每一个可选值都用模式匹配的方式来获取值在代码书写上就比较繁琐,我们还可以使 用 if let 的方式来进行可选值绑定。

case .some(let v):
        array.remove(at: array.firstIndex(of: v)!)

除了使用 if let 来处理可选值之外,我们还可以使用 gurad let 来简化我们的代码。

gurad letif let 刚好相反,gurad let 守护一定有值。如果没有,直接返回。 通常判断是否有值之后,会做具体的逻辑实现,通常代码多 如果用 if let t 凭空多了一层分支, gurad let 是降低分支层次的办法。