Swift的Guard语句

作者: 97c49dfd1f9f | 来源:发表于2015-07-31 01:06 被阅读45382次

    本篇文章翻译自:
    http://ericcerney.com/swift-guard-statement/
    原作者:ecerney
    原文章发布于2015-06-10
    *译者注:该语法为swift2.0新特性,目前(2015-07-30)仅xcode 7 beta支持,xcode6并不支持。


    最开始在Apple的Platform State of the Union看见swift的guard语句的时候,我当时不太理解以后会有什么理由能用到它。这个语句的介绍如下:

    与if语句相同的是,guard也是基于一个表达式的布尔值去判断一段代码是否该被执行。与if语句不同的是,guard只有在条件不满足的时候才会执行这段代码。你可以把guard近似的看做是Assert,但是你可以优雅的退出而非崩溃。

    即使看了一些例子,我还只是认为这不过是一种更让人困惑的方式,实现我们早已经能够用可选绑定(optional binding)或者单独的if-else语句实现的目的。
    直到我开始在Twitter conversation讨论关于这个语句的时候,我才意识到这个语法真的有一些
    非常有意思的优点。

    Swift Guard保镖Swift Guard保镖

    具体细节

    让我们用一个简单的对比来比较一下现在的写法和用全新guard语句的写法:

    func fooManualCheck(x: Int?) {
        if x == nil || x <= 0 {
            // 不符合值的要求时,写点代码
            return
        }
        
        // 使用x
        x!.description
    }
    

    这是最基本的Objective-C方式来保证一个变量真的存在并符合一个条件。没什么大问题,但是有一些缺点:

    1. 你是在检查一个不符合你期望的条件,而非检查你想要的值。如果你加了一堆像这样的条件判断,代码就变的不好理解。你在这里其实是等着你的条件通不过。
    2. 如果前面条件判断的结果不符合了,你还得将你的变量强制拆包。

    Swift通过可选绑定让问题变得简单了一些,并解决了上面的部分缺点:

    func fooBinding(x: Int?) {
        if let x = x where x > 0 {
            // 使用x
            x.description
        }
        
        // 如果值不符合条件判断,就执行下面的代码
    }
    

    这个函数没有了第一个函数的2个缺陷,但引入了一个新的。你把你要写的代码都放在了所有条件判断中,而不是之后。你可能不会马上意识到这个问题,但是你可以想象在你的代码被执行之前,如果嵌套了好多需要被匹配的条件判断,这会变的多难读懂。

    对此的解决方法是先对每个条件逐一做检查,如果不符合条件判断就退出。这就会让人容易看出来什么条件会让这个函数退出。

    我听说过这个叫保镖模式(Bouncer Pattern),这个模式十分的合理。你要在坏情况进门之前把它们挡出去。这让你每次只考虑一种情况,而不用去搞清楚如何同时将所有的条件判断安排在一起。

    这就是guard语句:

    func fooGuard(x: Int?) {
        guard let x = x where x > 0 else {
            // 变量不符合条件判断时,执行下面代码
            return
        }
        
        // 使用x
        x.description
    }
    

    使用guard语句将上述的3个问题一并解决:

    1. 是对你所期望的条件做检查,而非不符合你期望的。又是和assert很相似。如果条件不符合,guard的else语句就运行,从而退出这个函数。
    2. 如果通过了条件判断,可选类型的变量在guard语句被调用的范围内会被自动的拆包 - 这个例子中该范围是fooGuard函数内部。这是一个很重要,却有点奇怪的特性,但让guard语句十分实用。
    3. 对你所不期望的情况早做检查,使得你写的函数更易读,更易维护。

    对非可选类型的变量这种用法也是奏效的:

    func fooNonOptionalGood(x: Int) {
        guard x > 0 else {
            // 变量不符合条件判断时,执行下面代码
            return
        }
        
        // 使用x
    }
     
    func fooNonOptionalBad(x: Int) {
        if x <= 0 {
            // 变量不符合条件判断时,执行下面代码
            return
        }
        
        // 使用x
    }
    

    总结

    希望上面这个简单的例子告诉你可以马上在你的swift代码中使用guard,从而让你的函数/方法更清楚。对我们来说评判一个新的特性很容易,只要去试一下,看看它对你来说有用没用。

    从Objective-C到swift的转变是巨大的,不仅仅是语法,还有你该怎样去看待你的代码架构。只有你主动的去改变自己的意向,每天扩展你自己的模式和方式,你才会从这个绝妙的新语言中收益。

    发现了什么其他好玩的东西就告诉我,这个语法对我来说也是新的。

    相关文章

      网友评论

      • 独白melody:swift关于闭包的操作可谓五花八门。if let guard else ?? as! ……
      • hahand:外国人解释东西,虽然说明方法可能很绕口,但是确实一针见血,直指目标。用guard而不用if原因有两个:1.是用 if 判断,要么在 else 里写处理,要么 判断条件 加非。2.很方便让人看出这段代码用来check的。换句话说,guard应该类似于OC里面的NSAssert, 在复杂逻辑前做好断言,会让调试bug事半功倍。
      • Lol刀妹:想请教下英文博客你们是怎么找到的
      • 5e144bc5ba83:学习了
      • 山林间迷雾能不能当障眼法的内容:func fooBinding(x: Int?) {
        if let x = x where x > 0 {
        // 使用x
        x.description
        }

        // 如果值不符合条件判断,就执行下面的代码
        }

        这里的x直接用了??? 不用解包了??? 楼主确定????
      • 莫云溪:学习了,的确比if else判断更直观。
      • 曹九朵_:学习了
      • 花郎:hi,提个小意见, if x == nil || x <= 0 应该写成if x == nil || x! <= 0,x值需要拆包才行。另外
        if let x = x where x > 0 {
        return
        }

        where关键字在我的编译器编译错误,提示我用,来分割不同的判断条件,这个有知道什么原因吗
        花郎:@黄联樵 嗯嗯,明白了,感谢
        黄联樵:swift 3 改成用逗号之后,很方便条件的一步一步嵌套,例如:

        if let a = x,
        let b = a,
        let c = b,
        let d = b,
        let e = d {
        **代码块**
        }
        else {
        **代码块**
        }
        黄联樵:现在swift 3是要用逗号,以前是where
      • valentizx:其实说白了 guard就是一个优雅的assert 我是这么理解的。。。因为没接触到更深层次的东西 不敢忘下评论
      • 麟young:函数实现时,guard打头只判断合理条件,保证判断条件简约;而只和else搭配,保证自身低调性,方便guard函数结束后,实现函数主要代码逻辑。总结:guard抽离合理判断条件和不重要逻辑。
      • leftwater:good
      • 巴图鲁:不错
      • af2ec2376e04:swift可有可无的语法糖太多
      • af2ec2376e04:只有带?的值有意义,其他的没意义
        深水日月:应该是需要“如果”这样的判断
      • 7a628d471f4c:请问 此篇及其他文章注明出处可转载吗?
      • 虚心若愚:兄弟看好你。
      • 虚心若愚:写的通俗易懂, 简直 太棒了。
      • 暮归倾城:感谢分享,学习了
      • Azen:吊吊吊!!
      • JinyaMax:学习了 。 简单来说,就是在声明判断条件时 可以直接写上你需要的条件(或者区间),而不必去谨慎地寻找该区间的补集 ,相对来说能减少错误(主要是遗漏),而且代码review时能思路能更清晰。
        piaodang1234:@happycoder 你把你要写的代码都放在了所有条件判断中,而不是之后。你可能不会马上意识到这个问题,但是你可以想象在你的代码被执行之前,如果嵌套了好多需要被匹配的条件判断,这会变的多难读懂。 这是不使用if的原因
        bf7edeaa0ddd:@JinyaTu if 不也可以直接写上需要的条件(或者区间吗)
        我的大好时光:@金亞 分析的好透彻
      • 七夕猪:例子中的 func fooNonOptionalBad: 是不是少写了 guard 关键字啊?
        七夕猪:@七夕猪 明白了,不是少写了,这个函数是辅助理解 func fooNonOptionalGood: 这个函数的吧。
      • David_Do:学习了。。。
      • 悲伤的盖茨比:感谢,学习了
      • GloryMan:学习了
      • 037e031e1cef:感谢分享
      • iTychoo:感谢, 学习了!
      • 贾亦真亦贾:学习了

      本文标题:Swift的Guard语句

      本文链接:https://www.haomeiwen.com/subject/dytvqttx.html