转载

Swift之&&,||,??实现原理

Swift之&&,||,??实现

operator

首先需要讲解swift中运算符是以函数的形式存在的,其中包含3种:

位置

  1. prefix 前置运算符
  2. infix 中间运算符
  3. postfix 后置运算符

配置

  1. associativity 结合性 (包含 left,right和none)
  2. precedence 优先级 (0-255)

&&

定义

我们可以看出结合性为左,优先级120,其次该函数有两个声明,在上一篇文章中提到 关于@autoclosure的作用

infix operator && {     associativity left     precedence 120 } public func &&<T : BooleanType>(lhs: T, @autoclosure rhs: () throws -> Bool) rethrows -> Bool public func &&<T : BooleanType, U : BooleanType>(lhs: T, @autoclosure rhs: () throws -> U) rethrows -> Bool 

实现

我们可以探索其中的源码,关于对其中 @inline 以及 @——transparent 感兴趣的朋友,可以在swift的docs中查看: TransparentAttr.tst

@inline(__always)  public func && <T : Boolean, U : Boolean>(   lhs: T, rhs: @autoclosure () throws -> U ) rethrows -> Bool {   return lhs.boolValue ? try rhs().boolValue : false }  @_transparent public func && <T : Boolean>(   lhs: T, rhs: @autoclosure () throws -> Bool ) rethrows -> Bool {   return lhs.boolValue ? try rhs().boolValue : false } 

分析

这里面让我开始非常疑惑的两个点:

  1. 为什么需要定义两个函数
  2. 为什么需要throws

以下均使用playground演示,首先我们来模拟系统的自定义一个运算符

infix operator &&& {     associativity left     precedence 120 } func &&& <T : BooleanType>(     lhs: T, @autoclosure rhs: () throws -> Bool     ) rethrows -> Bool {     "test1"     return lhs.boolValue ? try rhs().boolValue : false }  func &&& <T : BooleanType, U : BooleanType>(     lhs: T, @autoclosure rhs: () throws -> U     ) rethrows -> Bool {     "test2"     return lhs.boolValue ? try rhs().boolValue : false }    struct Fraction {     let numerator: Double   // 分子     let denominator: Double   // 分母     init(numerator: Double, denominator: Double) {         self.numerator = numerator         self.denominator = denominator     } } // 使其能够使用获取Bool值 extension Fraction: BooleanType {     var boolValue: Bool {         // 不等于0即为真         return numerator / denominator != 0     } } // 测试 let username = "admin" let password = "123456" let success =  username.characters.count > 0 &&& password.characters.count > 0  // true 并且输出test1 success &&& Fraction(numerator: 100, denominator: 50) // true 并且输出test2 

从上可以看出:

  1. &&& 左右返回值都为 Bool 类型的时候会调用第一个函数,即上面看到的 <T : BooleanType>
  2. &&& 右边为自定义类型的使用会调用调用第二个函数,即上面看到的 <T : BooleanType, U : BooleanType>

那么接下来解决第二个问题,为什么会 throws 呢?也就是说上述两个函数,如果你把 throwsrethrows 都去掉,其余 &&& 照常可以执行,那为什么会加入这两个关键字呢?

首先介绍下两个关键字:

rethrows 和  throws 它们都是标记了一个方法应该抛出错误。但是  rethrows 一般用在参数中含有可以  throws 的方法的高阶函数中

那么我们来继续为 struct Fraction 添加一些处理,分母不能为0,那这种情况我们可以抛出异常来处理,重新定义之后,如下

struct Fraction {     // 添加错误类型     enum Error: ErrorType {         case DenominatorZero     }     let numerator: Double   // 分子     let denominator: Double   // 分母     init(numerator: Double, denominator: Double) throws {         // 保证分母不能为0         guard denominator != 0 else {             throw Error.DenominatorZero         }         self.numerator = numerator         self.denominator = denominator     } } // 使其能够使用获取Bool值 extension Fraction: BooleanType {     var boolValue: Bool {         // 不等于0即为真         return numerator / denominator > 0     } } // 重新测试 let username = "admin" let password = "123456" let success =  username.characters.count > 0 &&& password.characters.count > 0  // true 并且输出test1 // 需要添加异常处理 do {     try success &&& Fraction(numerator: 100, denominator: 50) // true 并且输出test2     try success &&& Fraction(numerator: 100, denominator: 0)  // 输出error } catch let error {     error } 

这样以来我们就能捕获到第二个闭包可能抛出的异常处理,会让我们所写的函数更加安全

那么同样大家可以试着去分析 ?? 以及 || ,我在这里就不累赘的介绍了

参考

错误和异常处理

swift源码Boolean

感谢

梁杰_numbbbbb

原文  http://archerzz.com/swift/operator.html
正文到此结束
Loading...