天天看點

Swift語言指南(九)--基本運算符

運算符(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:

Swift語言指南(九)--基本運算符

如圖所示,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。

Swift語言指南(九)--基本運算符

自增與自減運算符

與 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

繼續閱讀