理解Swift中的Optional

让我们来看一个例子:

class Father{
    var child: Child = Child()
    ...
}
class Child{
    var pet: Pet = Pet()
}
class Pet{
    func jump(){
        print("pet jump")
    }
}

如上,父亲有小孩,小孩有狗,狗会叫。
但是有可能小孩没有宠物呢?怎么办?
这不是很简单吗,我们来改写下小孩类不就好了:

class Child{
    var pet: Pet = nil
}

Oh no,编译器报错了。啥?nil不能初始化pet?
为啥会出错呢,原因是Swift中,所有的变量都需要初始化,不能为nil。

那咋办?Swift用Optional来解决这个问题。


Optional

我们改写一下小孩类:

class Child{
    var pet: Pet?
}

Pet?等价于Optional<Pet>
就是说你也可以这么写:

class Child{
    var pet: Optional<Pet>
}

这时,小孩就没有小狗了,变量pet变成了一个Optional类型。
我们可以把Optional想像成一个盒子,盒子里面装了变量的值,当然盒子也有可能是空的。
那么上面的例子现在就变成:父亲有小孩,小孩有装狗用的盒子,盒子里面没有小狗。
要把小狗装进盒子很简单:

var child: Child = Child() child.pet = Pet()


Optional的 拆包(unwrapping)

强拆(Force unwrapping)

好了,现在我们把宠物取出来让他跳一下吧!

var pet = child.pet
pet.jump()

啊?啥又报错了。注意了,这时的pet变量的类型不是Pet,而是Optional,Optional没有跳的方法,他是个盒子,我们要把真正的宠物取出来才能让它跳。

这样取:

var pet = child.pet!
pet.jump()  //输出:pet jump

像上面这样,加个感叹号就可以把把东西从Optional里取出来了。这种方式叫做强拆,不管三七二十一,里面的东西给我拿出来。

我们应该尽量少直接用强拆,因为我们不知道盒子里面有没有东西。像下面这样就会报错:

var child: Child = Child()
var pet = child.pet!

因为我们没有给child的pet盒子装宠物,所以我们要加个判断,看看盒子里面是不是空的:

var child: Child = Child()
if (child.pet != nil){
    var pet = child.pet!
    pet.jump()
}else{
    print("Box is empty");
}
//输出Box is empty

每次都这样判断很麻烦吖,而且万一忘记了就可能会报错,更重要的是这个报错是运行时报的,编辑器检查不出来。(这就是常见的空指针异常)

if let

Swift提供了一种更好的方法:

var child = Child()
if let pet = child.pet{
    pet.jump()
}else{
   print("Box is empty");
}
//输出Box is empty

这样,如果有宠物直接取出来放到pet常量里面,没有的话就执行else。(连拆包的感叹号也不用写了呢)

问号拆

很多情况下我们想child有pet我们就让它跳,没有就不做处理。
写起来是这样的:

var child = Child()
if let pet = child.pet{
    pet.jump()
}

Swift给我们提供了个更方便的写法:

var child = Child()
child.pet?.jump()

上面这段代码什么都不会发生,如果pet为空,那么问号之后的代码都不会执行。
如果Father中的Child也是个Optional,我们还可以这样:

var father = Father()
father.child?.pet?.jump()

解释起来就是,father有child吗?child有pet吗?pet jump

谢谢阅读~

相关文章

软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘...
现实生活中,我们听到的声音都是时间连续的,我们称为这种信...
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿...
【Android App】实战项目之仿抖音的短视频分享App(附源码和...
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至...
因为我既对接过session、cookie,也对接过JWT,今年因为工作...