操作符是一种用于检查、操作、组合值的特殊的符号或短语。比如将两个值相加(let i = 1 + 2
)的加号(+)。更复杂的比如逻辑与(&&)、自增(++i:表示给i加上一个1后返回)。
Swift支持大多数标准C的操作符,而且为了消除错误增加了一些功能。为了与运算符(==)区分开来,赋值操作符(=)不返回任何值。算术运算符(+
,-
,*
,/
,%
等)检测和避免值的溢出,在处理数字时,以免出现比存储类型允许的值范围大或小这些意想不到的结果。你可以使用在Overflow Operators描述的Swift溢出操作符来进行溢出值的展现。
与C不同的是,Swift在浮点数的计算中可以使用余数(%)。Swift提供了2种域操作符(a..<b和a...b)代表一系列值,而C中没有这种操作符。
这一节中描述了Swift常用的操作符。而Advanced Operators一文中描述的是高级操作符,并描述了如何定义您自己的自定义操作符和如何继承自己的自定义类型的标准操作符。
操作符有一元、二元、三元:
操作符影响的值叫操作数,在表达式1+2中,加号(+)是一个二元操作符,它有2个操作数:1和2.
赋值运算符(a=b)表示用b的值初始化或更改a的值。
let b = 10 var a = 5 a = b // a is now equal to 10
let (x, y) = (1, 2) // x is equal to 1, and y is equal to 2
与C和OC中的赋值元素符不同之处在于,Swift中的赋值运算符自身是不返回值的。下面的语句是无效的:
if x = y { // this is not valid, because x = y does not return a value }
Swift为所有数字运算提供了4中算术运算符:加(+)减(-)乘(*)除(/).
1 + 2 // equals 3 5 - 3 // equals 2 2 * 3 // equals 6 10.0 / 2.5 // equals 4.0
加号(+)可用于字符串的连接:
"hello, " + "world" // equals "hello, world"
两个字符的值,一个字符和一个字符串的值,可以通过加号形成一个新的string值。
其他详情查看Concatenating Strings and Characters.一文。
取余操作符(a%b)计算出a可以容纳多少个b,返回剩下的余数。
注意 取余运算符在其他语言中称为模数运算子。严格来说,Swift中的取余运算符在负数操作上要比模数运算子更有意义。
很显然,9中含有2个4.然后剩下1。在Swift中,可以写成:
9 % 4 // equals 1
为了确定a%b的答案,取余运算符(%)下面的方程式返回reminder作为它的结果输出。
a = (b × some multiplier) + remainder
将9和4放入上面的方程式中
9 = (4 × 2) + 1
当a的值是负数时,取余运算符同样适用。
-9 % 4 // equals -1
将-9和4放入方程式中
-9 = (4 × -2) + -1
标志符b是忽略a的符号的,所以a%b和a%-b的值是一样的。
与C和OC不同的是,在Swift中取余计算同样适用于浮点数。
8 % 2.5 // equals 0.5
该例中,8包含3个2.5.余下一个0.5。所以上述表达式返回一个double类型的数0.5.
和C一样,Swift提供自增(++)自减(--)运算符,代表在一个数上进行加1和减1操作。任何整型和浮点型的变量都可以使用。
var i = 0 ++i // i now equals 1
每一次调用++i,i的值都会加1.事实上,++i就是i=i+1的意思。类似的--i就是i=i-1的意思。++和--标识符既可以作为前缀也可以作为后缀。++i和i++都是加1的操作。同理,--i和i--都是减1的操作。
注意操作符对i的修改和返回的值。如果你只想对存储在i中的值减1或加1,你可以不用在意返回值。如果你想使用返回值,要注意++和--的前缀和后缀的区别。
如下面例子:
var a = 0 let b = ++a // a and b are now both equal to 1 let c = a++ // a is now equal to 2, but c has been set to the pre-increment value of 1
上面的例子中,let b=++a会先加1在返回。let c=a++中a会先返回再加1.所以c会得到a之前的值1.然后a变为2.
如果你没有特殊的需求,推荐在任何情况下都使用++或--标识符。因为他们在修改变量后返回值方面有典型的预期表现。
有符号的数字可以通过在前面添加减号(-)来转换值,称为一元减操作符。
let three = 3 let minusThree = -three // minusThree equals -3 let plusThree = -minusThree // plusThree equals 3, or "minus minus three"
有符号的数字可以通过在前面添加加号(+)来转换值,称为一元加操作符。
let minusSix = -6 let alsoMinusSix = +minusSix // alsoMinusSix equals -6
和C一样,Swift也提供将赋值运算符(=)与其他操作符组合在一起,称为复合赋值运算符。下面的例子中的复合赋值运算符为加等(+=)运算符。
var a = 1 a += 2 // a is now equal to 3
注意 复合运算符没有返回值,你不能写成let c = a+=2.这和上面的提到的自增和自减效果是不一样的
Swift支持所有C的比较运算符。
注意 Swift也提供2中特性的比较操作符(===和!==),这是用来比较继承同一个对象的子对象是否是同一个实例。想了解更多,请看<span class="x-name"><a target=_blank href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-XID_95" data-id="//apple_ref/doc/uid/TP40014097-CH13-XID_95">Classes and Structures</a></span>一文。
每一个比较操作符都会返回一个Bool类型的值来表示表达式是否为真。
1 == 1 // true, because 1 is equal to 1 2 != 1 // true, because 2 is not equal to 1 2 > 1 // true, because 2 is greater than 1 1 < 2 // true, because 1 is less than 2 1 >= 1 // true, because 1 is greater than or equal to 1 2 <= 1 // false, because 2 is not less than or equal to 1
let name = "world" if name == "world" { println("hello, world") } else { println("I'm sorry \(name), but I don't recognize you") } // prints "hello, world", because name is indeed equal to "world"
三元条件运算符是含有3部分的特殊运算符。其形式为question?answer1:answer2.它会根据questions得出的Bool值来选择后面2个表达式之一来进行计算。如果question的值为true那么就会选择answer1来计算,反之选择answer2来计算。
三元田间运算符类似下面的形式:
if question { answer1 } else { answer2 }
let contentHeight = 40 let hasHeader = true let rowHeight = contentHeight + (hasHeader ? 50 : 20) // rowHeight is equal to 90
let contentHeight = 40 let hasHeader = true var rowHeight = contentHeight if hasHeader { rowHeight = rowHeight + 50 } else { rowHeight = rowHeight + 20 } // rowHeight is equal to 90
rowHeight
值初始化只需一行代码就可以搞定。比第二个例子更简洁。而且rowHeight也不需要是变量,因为它的值在if语句里不会改变。
三元运算符对于2个表达式的运算是很高效的,但是要小心使用。如果过度使用会使代码变得晦涩难懂。避免组合使用多种三元运算符。
Swift提供2种范围运算符,表示值的范围。
封闭运算符(a...b)代表了a到b的范围,而且还包括a和b。当你想包括一系列数中的所有数,例如用for 。。in表达式时,使用封闭运算符是更好的。
for index in 1...5 { println("\(index) times 5 is \(index * 5)") } // 1 times 5 is 5 // 2 times 5 is 10 // 3 times 5 is 15 // 4 times 5 is 20 // 5 times 5 is 25
半封闭运算符(a..<b)表示a到b范围内的数,但是不包括b。叫它半封闭的原因是它包括第一个数但是不包含最后一个数。
当你用在数组这种以0为起始值的列表中,半封闭是很有用的。遍历数组(不包括最后一个)是很方便的。
et names = ["Anna", "Alex", "Brian", "Jack"] let count = names.count for i in 0..<count { println("Person \(i + 1) is called \(names[i])") } // Person 1 is called Anna // Person 2 is called Alex // Person 3 is called Brian // Person 4 is called Jack
但是实际代码中发现a..<b这种方式并不正确,而a..b有半闭的效果。
<span style="color:#FF0000;">let a = 4 for i in 0..a { println(i) } let b = 5 for i in 0...b { println(i) }</span>
且a..b和a...b中间不要有空格,不然也会有问题
逻辑运算修改和组合逻辑值true和false.和C中的逻辑元素一样,Swift也提供3中逻辑运算符。
逻辑非(!a)倒置布尔值,true的值变为false,false的值变为true.逻辑非是个前缀操作符,紧贴在布尔值的前面,中间不能有空格,可以读作not a。看下面的例子。
let allowedEntry = false if !allowedEntry { println("ACCESS DENIED") } // prints "ACCESS DENIED"
表达式if !allowedEntry意思是if not allowed entry.如果allowedEntry的值是false,括号里的代码才能执行。在上面的例子中,认真挑选布尔值的常量和变量会使代码变得易读和简洁,避免了双重否定和混乱的语句出现。
逻辑与运算符(&&)比如符号两边的表达式都必须是true,运算结果才是true.如果有一个值是false,那么表达式就是false.如果第一个值为false,那么就不会计算第二个值就直接返回false,因为表达式的值肯定为false,无需再继续第二个表达式的值。这种方式称为短路计算。
下面的例子会考虑2个布尔值,而且2个布尔值都是true时才会继续处理。
let enteredDoorCode = true let passedRetinaScan = false if enteredDoorCode && passedRetinaScan { println("Welcome!") } else { println("ACCESS DENIED") } // prints "ACCESS DENIED"
逻辑或运算符是把操作符放在两个相邻字节中间。你可以使用它创建逻辑表达式,这种表达式中的任何一个值为true,表达式就会返回true.和上面的逻辑与一样,逻辑或也是采用短路的形式处理表达式的。如果表达式坐标的值为true,就不会再执行右边的表达式。因为无论右边的值为什么,表达式的值都为true.
下面的例子中,第一个Bool值为false,但是第二个Bool值为true,那么表达式的值就为true.
let hasDoorKey = false let knowsOverridePassword = true if hasDoorKey || knowsOverridePassword { println("Welcome!") } else { println("ACCESS DENIED") } // prints "Welcome!"
你可以通过组合多个逻辑运算符形成一个复合的表达式。
if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword { println("Welcome!") } else { println("ACCESS DENIED") } // prints "Welcome!"
上面的例子用逻辑与(&&)和逻辑或(||)组合形成了一个复合表达式。但是逻辑与和逻辑或只处理符号两边的表达式,所以上面的复合表达式可以理解为3个表达式的合体。
上面的表达式可以理解为:
如果我进入大门,通过视网膜扫描或者有门钥匙或者知道门的密码,我就可以进入房间。基于enteredDoorCode、passedRetinaScan和hasDoorKey的值,第一次或的运算结果是false.但是你知道密码,整个表达式的结果也为true.
有时在你不是非常需要括号的时候,我们推荐你使用括号在规范你的代码是很有必要的。在上面的事例代码中,在第一个部分打上括号是很有利于代码的阅读的。
if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword { println("Welcome!") } else { println("ACCESS DENIED") } // prints "Welcome!"
括号可以使得开头的2个表达式从整个表达式中独立出来,我们这时只考虑这2个值。表达式的输出结果也不会因为加了括号而发生变化,但是表达式变得易读。易读性优于简洁性。使用括号会使你的意图更清晰。