運算符(operator)是用來檢查,改變或合并值的一種特殊符号或短語。例如,加号運算符讓兩個數字相加(如:let i = 1 + 2),還有些更複雜的運算符,如邏輯與運算符(&&)(如:if enteredDoorCode && passedRetinaScan)和自增運算符(++i)(将 i 的值加 1 的便捷寫法)。
Swift 支援标準C語言的大多數運算符,并且改進了一些特性以規避常見的代碼錯誤。指派運算符(=)是沒有傳回值的,這樣是為了避免在使用等于運算符(==)時誤用了指派運算符(=)。算術運算符(+,-,*,/,% 等等)會偵測并阻止值溢出,可避免在運算時超出存儲類型的值域範圍(比實際運算結果大或小,或不精準--Joe.Huang)。如果需要支援溢出行為,可以選用 Swift 的溢出運算符,詳情可見 溢出運算符(後面章節譯到)。
與C語言不同的是,Swift 允許對浮點數求餘(%)。Swift 還提供了C語言所沒有的兩個區間運算符(a..b和a...b),作為表示值域範圍的便捷寫法。
本章介紹 Swift 中的常用運算符。進階運算符 (後面章節譯到) 一章涵蓋了 Swift 中的進階運算符,并講解了如何自定義運算符,以及讓标準運算符支援自定義類型的運算。
運算符術語
運算符分為一進制,二進制,三元運算符:
· 一進制運算符(unary operator)對單個目标進行運算(如 -a)。一進制運算符字首(unary prefix operator)緊跟運算目标之前(如 !b),而一進制運算符字尾(unary postfix operator)則緊跟運算目标之後(如 i++)。 · 二進制運算符(binary operator)對兩個目标進行運算(如 2 + 3),它們屬于中綴(infix)運算符,因為(運算符号)出現在兩個運算目标之間。 · 三元運算符(ternary operator)對三個目标進行運算。與 C 語言一樣,Swift 隻有一個三元運算符:三元條件運算符(即 a ? b : c)。
運算符操作的值稱為運算元(operands)。在表達式 1 + 2 中,+ 符号是二進制運算符,它的兩個運算元為值 1與值 2。
指派運算符
指派運算符(assignment operator,a = b)用 b 的值初始化或更新 a 的值:
如果指派語句的右側是一個包含多個值的元組,元組的元素可一次性用多個常量或變量分解提取出來(上一章講解元組時提到過分解元組值的方法--Joe.Huang):
與 C 或 Objective-C 語言的指派運算符不同,Swift 語言的指派運算符本身沒有傳回值。是以下面的語句不正确:
該特性可避免在使用等于運算符(==)時誤用了指派運算符(=)。通過否認 if x = y 的有效性,Swift 将幫助你規避代碼中出現這樣的錯誤。
算術運算符
Swift支援對所有數字類型使用四種标準算術運算符:
· 加:+ · 減:- · 乘:* · 除:/
與 C / Objective-C 語言的算術運算符不同,Swift 的算術運算符預設不允許值溢出。如果需要支援溢出行為,可以選用 Swift 的溢出運算符(如,a &+ b),詳情可見 溢出運算符(後面章節譯到)。
加号運算符也支援 String 拼接:
可以将兩個 Character (字元,Unicode字元--Joe.Huang)值相加,或将一個 Character 值與一個 String 值相加,得到新的 String 值:
詳見 字元與字元串拼接 (後面章節譯到):
求餘運算符
求餘運算符(remainder operator,a % b)求出 a 包含多少個 b,并傳回剩餘的值(即整除後的餘數 remainder)。
注:
求餘運算符(%)在其他語言中也稱作求模運算符(modulo operator)。但對負數的運算結果表明:Swift 語言的實作是嚴格的求餘操作,而非求模操作。
求餘運算符的原理如下。 要計算 9 % 4,首先要求出 9 裡面包含多少個 4:
如圖所示,9 裡面包含兩個 4,餘數是 1 (橙色部分)。
Swift中的寫法如下:
要求出 a % b 的結果,% 運算符會計算下面的等式,并将餘數作為輸出結果傳回:
其中 some multiplier 是 a 中能裝下 b 的最大數目。
把 9 和 4 代入等式:
a 為負數時,求餘方法不變:
把 -9 和 4 代入等式:
得到的餘數值為-1。
b 為負值(-b)時,b 的負号将被忽略。是以 a % b 與 a % -b 總是傳回相同的結果。
浮點數的求餘計算
與 C / Objective-C 語言的餘數運算符不同,Swift 的餘數運算符還能對浮點數進行求餘計算:
上例中,8 除以 2.5 等于 3,餘數為 0.5,是以餘數運算符傳回 Double 型的值 0.5。
自增與自減運算符
與 C 語言類似,Swift 也提供了自增運算符(++)與自減運算符(--),作為将數字變量的值加上或減去 1 的便捷寫法。任何整型或浮點型的變量都可以使用這兩個運算符。
每次調用 ++i 時,i 的值就會增加 1。本質上,++i 就是 i = i + 1 的便捷寫法。類似地,--i 也相當于 i = i - 1。
++ 與 -- 兩對符号可以作為字首或字尾運算符使用。++i 與 i++ 均可用來将 i 的值加 1。類似地,--i 與 i-- 均可用來将 i 的值減去 1。
注意,這些運算符不僅會改變 i 的值,還會傳回一個值。如果你隻需要将自增或自減後的值存放在 i 中,那你可以忽略運算符的傳回值。但如果你确實要用到傳回值,要注意字首及字尾運算符傳回值的差異,規則如下:
· 如果運算符在變量名前面,先改變它的值,再傳回其值。 · 如果運算符在變量名後面,先傳回原值,再改變它的值。
如例:
在上例中,let b = ++a 先增加 a 的值(加1),然後才傳回它的值。是以 a 與 b 都等于新的值 1。
但是,let c = a++ 先傳回 a 的原值(加1之前的值),然後才增加 a 的值。即 c 得到了原值 1,然後 a 被更新為新值 2。
除非你需要利用 i++ 的這一特性,建議你在所有情況下都使用 ++i 與 --i,因為它們先修改 i 再傳回修改後的值的動作更符合邏輯。
一進制減号運算符
數值前加上字首 - ,這個字首運算符 - 就稱為一進制減号運算符:
一進制減号運算符(-)緊靠所要操作的值之前,無需任何空格。
一進制加号運算符
一進制加号運算符(+)直接傳回所操作的值,不作任何處理:
盡管一進制加号運算符實際上不作任何運算,代碼中仍然可以用它(提供語義資訊,一進制減号運算符表示負數,一進制加号運算符表示正數--Joe.Huang)與表示負數的一進制減号運算符形成對比。
複合指派運算符
與 C 語言類似,Swift 也提供複合指派運算符(compound assignment operator)将指派運算符(=)與其他運算組合起來使用。例如加法指派運算符(addition assignment operator,+=):
上例中的表達式 a = a + 2 簡寫為 a += 2,加法和指派兩項操作組合為一個單項操作,執行時非常高效。
注: 複合指派操作沒有傳回值,即,你不能寫:let b = a += 2,這一操作與前面所提到的自增自減操作是不同的。
複合指派運算符的完整清單可在 表達式 一章中找到(後面章節譯到)。
比較運算符
Swift支援标準C 的比較運算符:
等于 (a == b) 不等于 (a != b) 大于 (a > b) 小于 (a < b) 大于等于 (a >= b) 小于等于 (a <= b) Swift還提供了恒等(===)和不恒等(!==)兩個鑒别運算符,你可以用它測試兩個對象是否引用了同一個對象執行個體。更多詳情請參考 類和結構 一章(後面章節譯到)。
每個比較運算符都會傳回一個 Bool 值,檢測表達式是否成立:
比較運算符常見于條件表達式中,如 if 條件句:
if 語句的更多介紹,詳見 流程控制 一章(後面章節譯到)。
三元條件運算符
三元運算符是一種特殊運算符,由三個部分組成,表現形式為:question ? answer1 : answer2。它是一種求值簡寫:根據 question 是否成立,從兩個表達式中取出一個并求值。
如果 question 成立,則計算 answer1 的結果并傳回其值;否則計算 answer2 并傳回其值。
三元條件運算符是如下代碼的縮寫:
下面的例子将計算表格某行的像素高度。如果該行有表頭,則行高應比内容高度高 50 個像素;如果沒有表頭,則隻高出 20 個像素:
上例便是如下代碼的縮寫:
使用三元條件運算符的例子說明,可以僅用一行代碼就将行高設為正确的值。這比(不用三元運算符的)第二個例子簡潔得多,并且行高(rowHeight)無需定義為變量,因為不再需要用 if 語句修改其值。
三元條件運算符提供了二選一的高效寫法。但使用三元條件運算符應小心。如果過度使用,其簡明性可能導緻代碼可讀性差。應避免将多個三元條件運算符組合在同一個語句中。
區間運算符
Swift有兩個區間運算法,是表示值域的簡便寫法。
閉區間運算符
區間運算符(a...b)定義了 a 到 b 的區間範圍,包括 a 和 b 在内。
閉區間運算符在需要周遊某區間内所有的值時很有用,如在 for-in 循環中使用:
for-in 語句的更多介紹,詳見 流程控制 一章(後面章節譯到)。
半閉區間運算符
半閉區間運算符(a..b)定義了從 a 到 b 的區間,但 b 不包括在内。說它是半閉區間,是因為第一個值包含在區間内,但最後一個值在區間外。
半閉區間在處理從 0 開始計數的清單時有用,如周遊數組,可從 0 數到清單的長度(但不包括長度值本身):
注意,數組包含四個元素,但因為是半閉區間,是以 0..count 隻數到 3(數組中最後一個元素的索引号)。數組更多資訊詳見 數組 一章(後面章節譯到)。
邏輯運算符
邏輯運算符是對布爾邏輯值 true 或 false 的組合操作,Swift 支援 C 及其衍生語言的三種标準邏輯運算符:
· 邏輯非(!a) · 邏輯與(a && b) · 邏輯或(a || b)
邏輯非運算符
邏輯非運算符對布爾值取反,即 true 變成 false,false 變成true。
邏輯非運算符是一個字首運算符,緊跟在所操作值的前面,沒有任何空格符。可以了解為"非",如下例:
代碼中的 if !allowedEntry 可以了解為“如果不允許進入”。随後的下一行代碼僅當“不允許進入”成立時才會執行;即 allowedEntry 為 false 時才執行。
如上例,布爾值常量及變量的名稱應謹慎選擇命名,方可確定代碼簡明又具可讀性,同時也應避免使用雙重否定或引起混淆的邏輯語句。
邏輯與運算符
(a && b)構造這樣的邏輯表達式:運算符兩側的值均為 true,整個表達式的求值結果才為 true。
如果有一個值為 false,整個表達式便為 false。事實上,如果第一個值為 false,第二個值将不執行求值運算,因為無論它為何值,整個表達式的值都不可能等于 true。這也被稱為短路求值(short-circuit evaluation)。
下面的例子驗證兩個值,當兩個值都為 true 時才能通路:
邏輯或運算符
(a || b)屬于中綴運算符,由兩個連續的豎線構成。它用來構造這樣的表達式:當兩個值中有一個為 true時,整個表達式為 true 。
與前面的邏輯與運算符一樣,邏輯或運算符在檢測它的兩個表達式時,也使用“短路求值”法。隻要邏輯或表達式左側為 true,其右側将不執行求值運算,因為這時右側的值對整個表達式的結果不再有影響。
下例中,第一個 Bool 值(hasDoorKey)為 false,但第二個值(knowOverridePassword)為 true。因為有一個值為 true,是以整個表達式的求值結果也為 true,是以允許通路:
組合使用邏輯運算符
可以将多個邏輯運算符組合起來構成一個較長的複合表達式。
本例使用多個 && 及 || 運算符構成一條較長的複合表達式。不過,&& 與 || 運算符操作的仍然是兩個值,是以該組合表達式實際上是由三個較短的表達式連立而成。它可以這樣了解:
如果我們輸入了正确的門禁密碼、并且通過了視網膜掃描;或者如果我們有門鑰匙;或者如果我們知道緊急的備用密碼,則允許通路。
根據 enteredDoorCode、passedRetinaScan、hasDoorKey 三個常量推算,前兩個小表達式的值均為 false。不過我們知道緊急的備用密碼(knowsOverridePassword 為 true),是以整個複合表達式的求值結果仍然為 true。
顯式括号
有時(從文法來看)括号并不是必需的,但加上括号卻很有用,它可以讓複雜表達式的易于閱讀。 在上例中,為組合表達式的第一部分加上括号,可使其意圖更明顯:
括号将前兩個值與其他值分隔開來,使其作為整體邏輯中的一種可選狀态的意思更加明顯。組合表達式的結果不會改變,但對讀者而言,整體意圖更加清晰。可讀性總是優先于簡潔性;應盡可能在合适的地方使用括号,使你的邏輯更加明晰。
謝謝,Swifter-QQ群:362232993,同好者進~
Fork:https://github.com/Joejo/Swift-lesson-for-chinese