三元条件运算(Ternary Conditional Operator)
三元条件运算的特殊在于它是有三个操作数的运算符,它的原型是问题?答案1:答案2。它简洁地表达根据问题成立与否作出二选一的操作。如果问题成立,返回答案1的结果; 如果不成立,返回答案2的结果。
使用三元条件运算简化了以下代码:
if question: { answer1 } else { answer2 }
这里有个计算表格行高的例子。如果有表头,那行高应比内容高度要高出50像素; 如果没有表头,只需高出20像素。
let contentHeight = 40 let hasHeader = true let rowHeight = contentHeight + (hasHeader? 50 : 20) // rowHeight 现在是 90
这样写会比下面的代码简洁:
let contentHeight = 40 let hasHeader = true var rowHeight = contentHeight if hasHeader { rowHeight = rowHeight + 50 } else { rowHeight = rowHeight + 20 } // rowHeight 现在是 90
第一段代码例子使用了三元条件运算,所以一行代码就能让我们得到正确答案。这比第二段代码简洁得多,无需将rowHeight定义成变量,因为它的值无需在if语句中改变。
三元条件运算提供有效率且便捷的方式来表达二选一的选择。需要注意的事,过度使用三元条件运算就会由简洁的代码变成难懂的代码。我们应避免在一个组合语句使用多个三元条件运算符。
区间运算符
Swift 提供了两个方便表达一个区间的值的运算符。
闭区间运算符
闭区间运算符(a...b)定义一个包含从a到b(包括a和b)的所有值的区间。 闭区间运算符在迭代一个区间的所有值时是非常有用的,如在for-in循环中:
for index in 1...5 { println("\(index) * 5 = \(index * 5)") } // 1 * 5 = 5 // 2 * 5 = 10 // 3 * 5 = 15 // 4 * 5 = 20 // 5 * 5 = 25
关于for-in,请看控制流。
半闭区间
半闭区间(a..b)定义一个从a到b但不包括b的区间。之所以称为半闭区间,是因为该区间包含第一个值而不包括最后的值。
半闭区间的实用性在于当你使用一个0始的列表(如数组)时,非常方便地从0数到列表的长度。
let names = ["Anna","Alex", "Brian", "Jack"] let count = names.count for i in 0..count { println("第 \(i + 1) 个人叫 \(names[i])") } // 第 1 个人叫 Anna // 第 2 个人叫 Alex // 第 3 个人叫 Brian // 第 4 个人叫 Jack
数组有4个元素,但0..count只数到3(最后一个元素的下标),因为它是半闭区间。关于数组,请查阅数组。
逻辑运算
逻辑运算的操作对象是逻辑布尔值。Swift 支持基于 C 语言的三个标准逻辑运算。
逻辑非(!a)
逻辑与(a && b)
逻辑或(a || b)
逻辑非
逻辑非运算(!a)对一个布尔值取反,使得true变false,false变true。
它是一个前置运算符,需出现在操作数之前,且不加空格。读作非 a,然后我们看以下例子:
let allowedEntry = false if !allowedEntry { println("ACCESS DENIED") } // 输出 "ACCESSDENIED"
if!allowedEntry语句可以读作 "如果 非 alowed entry。",接下一行代码只有在如果"非 allow entry" 为true,即allowEntry为false时被执行。
在示例代码中,小心地选择布尔常量或变量有助于代码的可读性,并且避免使用双重逻辑非运算,或混乱的逻辑语句。
逻辑与
逻辑与(a && b)表达了只有a和b的值都为true时,整个表达式的值才会是true。
只要任意一个值为false,整个表达式的值就为false。事实上,如果第一个值为false,那么是不去计算第二个值的,因为它已经不可能影响整个表达式的结果了。这被称做 "短路计算(short-circuit evaluation)"。
以下例子,只有两个Bool值都为true值的时候才允许进入:
let enteredDoorCode = true let passedRetinaScan = false if enteredDoorCode &&passedRetinaScan { println("Welcome!") } else { println("ACCESS DENIED") } // 输出 "ACCESSDENIED"
逻辑或
逻辑或(a || b)是一个由两个连续的|组成的中置运算符。它表示了两个逻辑表达式的其中一个为true,整个表达式就为true。
同逻辑与运算类似,逻辑或也是"短路计算"的,当左端的表达式为true时,将不计算右边的表达式了,因为它不可能改变整个表达式的值了。
以下示例代码中,第一个布尔值(hasDoorKey)为false,但第二个值(knowsOverridePassword)为true,所以整个表达是true,于是允许进入:
let hasDoorKey = false let knowsOverridePassword = true if hasDoorKey || knowsOverridePassword { println("Welcome!") } else { println("ACCESS DENIED") } // 输出"Welcome!"
组合逻辑
我们可以组合多个逻辑运算来表达一个复合逻辑:
if enteredDoorCode &&passedRetinaScan || hasDoorKey || knowsOverridePassword { println("Welcome!") } else { println("ACCESS DENIED") } // 输出 "Welcome!"
这个例子使用了含多个&&和||的复合逻辑。但无论怎样,&&和||始终只能操作两个值。所以这实际是三个简单逻辑连续操作的结果。我们来解读一下:
如果我们输入了正确的密码并通过了视网膜扫描; 或者我们有一把有效的钥匙; 又或者我们知道紧急情况下重置的密码,我们就能把门打开进入。
前两种情况,我们都不满足,所以前两个简单逻辑的结果是false,但是我们是知道紧急情况下重置的密码的,所以整个复杂表达式的值还是true。
使用括号来明确优先级
为了一个复杂表达式更容易读懂,在合适的地方使用括号来明确优先级是很有效的,虽然它并非必要的。在上个关于门的权限的例子中,我们给第一个部分加个括号,使用它看起来逻辑更明确:
if (enteredDoorCode &&passedRetinaScan) || hasDoorKey || knowsOverridePassword { println("Welcome!") } else { println("ACCESS DENIED") } // 输出"Welcome!"
这括号使得前两个值被看成整个逻辑表达中独立的一个部分。虽然有括号和没括号的输出结果是一样的,但对于读代码的人来说有括号的代码更清晰。可读性比简洁性更重要,请在可以让你代码变清晰地地方加个括号吧!