首先需要讲解swift中运算符是以函数的形式存在的,其中包含3种:
我们可以看出结合性为左,优先级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 }
这里面让我开始非常疑惑的两个点:
以下均使用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
从上可以看出:
&&&
左右返回值都为 Bool
类型的时候会调用第一个函数,即上面看到的 <T : BooleanType>
&&&
右边为自定义类型的使用会调用调用第二个函数,即上面看到的 <T : BooleanType, U : BooleanType>
那么接下来解决第二个问题,为什么会 throws
呢?也就是说上述两个函数,如果你把 throws
和 rethrows
都去掉,其余 &&&
照常可以执行,那为什么会加入这两个关键字呢?
首先介绍下两个关键字:
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