運算符(operator)是用來檢查,改變或合併值的一種特殊符號或短語。例如,加號運算符讓兩個數字相加(如:let i = 1 + 2),還有些更復雜的運算符,如邏輯與運算符(&&)(如:if enteredDoorCode && passedRetinaScan)和自增運算符(++i)(將 i 的值加 1 的便捷寫法)。git
Swift 支持標準C語言的大多數運算符,而且改進了一些特性以規避常見的代碼錯誤。賦值運算符(=)是沒有返回值的,這樣是爲了不在使用等於運算符(==)時誤用了賦值運算符(=)。算術運算符(+,-,*,/,% 等等)會偵測並阻止值溢出,可避免在運算時超出存儲類型的值域範圍(比實際運算結果大或小,或不精準--Joe.Huang)。若是須要支持溢出行爲,能夠選用 Swift 的溢出運算符,詳情可見 溢出運算符(後面章節譯到)。github
與C語言不一樣的是,Swift 容許對浮點數求餘(%)。Swift 還提供了C語言所沒有的兩個區間運算符(a..b和a...b),做爲表示值域範圍的便捷寫法。算法
本章介紹 Swift 中的經常使用運算符。高級運算符 (後面章節譯到) 一章涵蓋了 Swift 中的高級運算符,並講解了如何自定義運算符,以及讓標準運算符支持自定義類型的運算。數組
運算符術語less
運算符分爲一元,二元,三元運算符:ide
· 一元運算符(unary operator)對單個目標進行運算(如 -a)。一元運算符前綴(unary prefix operator)緊跟運算目標以前(如 !b),而一元運算符後綴(unary postfix operator)則緊跟運算目標以後(如 i++)。post
· 二元運算符(binary operator)對兩個目標進行運算(如 2 + 3),它們屬於中綴(infix)運算符,由於(運算符號)出如今兩個運算目標之間。測試
· 三元運算符(ternary operator)對三個目標進行運算。與 C 語言同樣,Swift 只有一個三元運算符:三元條件運算符(即 a ? b : c)。ui
運算符操做的值稱爲運算元(operands)。在表達式 1 + 2 中,+ 符號是二元運算符,它的兩個運算元爲值 1與值 2。this
賦值運算符
賦值運算符(assignment operator,a = b)用 b 的值初始化或更新 a 的值:
1 let b = 10 2 var a = 5 3 a = b 4 // a is now equal to 10 5 //a如今等於10
若是賦值語句的右側是一個包含多個值的元組,元組的元素可一次性用多個常量或變量分解提取出來(上一章講解元組時提到過度解元組值的方法--Joe.Huang):
1 let (x, y) = (1, 2) 2 // x is equal to 1, and y is equal to 2 3 //x等於1,y等於2
與 C 或 Objective-C 語言的賦值運算符不一樣,Swift 語言的賦值運算符自己沒有返回值。所以下面的語句不正確:
1 if x = y { 2 // this is not valid, because x = y does not return a value 3 // 這是無效的,由於 x = y 不會返回一個值 (x==y才能夠,--Joe.Huang) 4 }
該特性可避免在使用等於運算符(==)時誤用了賦值運算符(=)。經過否定 if x = y 的有效性,Swift 將幫助你規避代碼中出現這樣的錯誤。
算術運算符
Swift支持對全部數字類型使用四種標準算術運算符:
· 加:+
· 減:-
· 乘:*
· 除:/
1 1 + 2 // 等於3 2 5 - 3 // 等於2 3 2 * 3 // 等於6 4 10.0 / 2.5 // 等於4.0
與 C / Objective-C 語言的算術運算符不一樣,Swift 的算術運算符默認不容許值溢出。若是須要支持溢出行爲,能夠選用 Swift 的溢出運算符(如,a &+ b),詳情可見 溢出運算符(後面章節譯到)。
加號運算符也支持 String 拼接:
"hello, " + "world" // 等於 "hello, world"
能夠將兩個 Character (字符,Unicode字符--Joe.Huang)值相加,或將一個 Character 值與一個 String 值相加,獲得新的 String 值:
1 let dog: Character = "" 2 let cow: Character = "
" 3 let dogCow = dog + cow 4 // dogCow 等於 "
"
詳見 字符與字符串拼接 (後面章節譯到):
求餘運算符
求餘運算符(remainder operator,a % b)求出 a 包含多少個 b,並返回剩餘的值(即整除後的餘數 remainder)。
注:
求餘運算符(%)在其餘語言中也稱做求模運算符(modulo operator)。但對負數的運算結果代表:Swift 語言的實現是嚴格的求餘操做,而非求模操做。
求餘運算符的原理以下。 要計算 9 % 4,首先要求出 9 裏面包含多少個 4:
如圖所示,9 裏面包含兩個 4,餘數是 1 (橙色部分)。
Swift中的寫法以下:
9 % 4 //等於 1
要求出 a % b 的結果,% 運算符會計算下面的等式,並將餘數做爲輸出結果返回:
a = (b × some multiplier) + remainder
其中 some multiplier 是 a 中能裝下 b 的最大數目。
把 9 和 4 代入等式:
9 = (4 × 2) + 1
a 爲負數時,求餘方法不變:
-9 % 4 // 等於 -1
把 -9 和 4 代入等式:
-9 = (4 × -2) + -1
獲得的餘數值爲-1。
b 爲負值(-b)時,b 的負號將被忽略。所以 a % b 與 a % -b 老是返回相同的結果。
浮點數的求餘計算
與 C / Objective-C 語言的餘數運算符不一樣,Swift 的餘數運算符還能對浮點數進行求餘計算:
8 % 2.5 // equals 0.5
上例中,8 除以 2.5 等於 3,餘數爲 0.5,所以餘數運算符返回 Double 型的值 0.5。
自增與自減運算符
與 C 語言相似,Swift 也提供了自增運算符(++)與自減運算符(--),做爲將數字變量的值加上或減去 1 的便捷寫法。任何整型或浮點型的變量均可以使用這兩個運算符。
1 var i = 0 2 ++i // i 如今等於 1
每次調用 ++i 時,i 的值就會增長 1。本質上,++i 就是 i = i + 1 的便捷寫法。相似地,--i 也至關於 i = i - 1。
++ 與 -- 兩對符號能夠做爲前綴或後綴運算符使用。++i 與 i++ 都可用來將 i 的值加 1。相似地,--i 與 i-- 都可用來將 i 的值減去 1。
注意,這些運算符不只會改變 i 的值,還會返回一個值。若是你只須要將自增或自減後的值存放在 i 中,那你能夠忽略運算符的返回值。但若是你確實要用到返回值,要注意前綴及後綴運算符返回值的差別,規則以下:
· 若是運算符在變量名前面,先改變它的值,再返回其值。
· 若是運算符在變量名後面,先返回原值,再改變它的值。
如例:
1 var a = 0 2 let b = ++a 3 // a 和 b 如今都等於 1,即改變a的值,再返回 4 let c = a++ 5 // a 如今等於 2, 但 c 仍是自增前的值 1,即先返回的a的原值,再改變其值
在上例中,let b = ++a 先增長 a 的值(加1),而後才返回它的值。所以 a 與 b 都等於新的值 1。
可是,let c = a++ 先返回 a 的原值(加1以前的值),而後才增長 a 的值。即 c 獲得了原值 1,而後 a 被更新爲新值 2。
除非你須要利用 i++ 的這一特性,建議你在全部狀況下都使用 ++i 與 --i,由於它們先修改 i 再返回修改後的值的動做更符合邏輯。
一元減號運算符
數值前加上前綴 - ,這個前綴運算符 - 就稱爲一元減號運算符:
1 let three = 3 2 let minusThree = -three // minusThree 等於 -3 3 let plusThree = -minusThree // plusThree 等於 3, 或等於 "減去 minusThree"
一元減號運算符(-)緊靠所要操做的值以前,無需任何空格。
一元加號運算符
一元加號運算符(+)直接返回所操做的值,不做任何處理:
1 let minusSix = -6 2 let alsoMinusSix = +minusSix // alsoMinusSix 等於 -6
儘管一元加號運算符實際上不做任何運算,代碼中仍然能夠用它(提供語義信息,一元減號運算符表示負數,一元加號運算符表示正數--Joe.Huang)與表示負數的一元減號運算符造成對比。
複合賦值運算符
與 C 語言相似,Swift 也提供複合賦值運算符(compound assignment operator)將賦值運算符(=)與其餘運算組合起來使用。例如加法賦值運算符(addition assignment operator,+=):
1 var a = 1 2 a += 2 3 // a 等於 3
上例中的表達式 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 值,檢測表達式是否成立:
1 1 == 1 // true, 由於 1 等於 1 2 2 != 1 // true, 由於 2 不等於 1 3 2 > 1 // true, 由於 2 大於 1 4 1 < 2 // true, 由於 1 小於 2 5 1 >= 1 // true, 由於 1 大於等於 1 6 2 <= 1 // false, 由於 2 大於等於 1
比較運算符常見於條件表達式中,如 if 條件句:
1 let name = "world" 2 if name == "world" { 3 println("hello, world") 4 } else { 5 println("I'm sorry \(name), but I don't recognize you") 6 //輸出(」對不起\name,我不認識你「) 7 } 8 // prints "hello, world", because name is indeed equal to "world" 9 //輸出 "hello world",由於 name 確實等於"world"
if 語句的更多介紹,詳見 流程控制 一章(後面章節譯到)。
三元條件運算符
三元運算符是一種特殊運算符,由三個部分組成,表現形式爲:question ? answer1 : answer2。它是一種求值簡寫:根據 question 是否成立,從兩個表達式中取出一個並求值。
若是 question 成立,則計算 answer1 的結果並返回其值;不然計算 answer2 並返回其值。
三元條件運算符是以下代碼的縮寫:
1 if question { 2 answer1 3 } else { 4 answer2 5 }
下面的例子將計算表格某行的像素高度。若是該行有表頭,則行高應比內容高度高 50 個像素;若是沒有表頭,則只高出 20 個像素:
1 let contentHeight = 40 2 let hasHeader = true 3 let rowHeight = contentHeight + (hasHeader ? 50 : 20) 4 // rowHeight(行高) 等於 90
上例即是以下代碼的縮寫:
1 let contentHeight = 40 2 let hasHeader = true 3 var rowHeight = contentHeight 4 if hasHeader { 5 rowHeight = rowHeight + 50 6 } else { 7 rowHeight = rowHeight + 20 8 } 9 // rowHeight(行高) 等於 90
使用三元條件運算符的例子說明,能夠僅用一行代碼就將行高設爲正確的值。這比(不用三元運算符的)第二個例子簡潔得多,而且行高(rowHeight)無需定義爲變量,由於再也不須要用 if 語句修改其值。
三元條件運算符提供了二選一的高效寫法。但使用三元條件運算符應當心。若是過分使用,其簡明性可能致使代碼可讀性差。應避免將多個三元條件運算符組合在同一個語句中。
區間運算符
Swift有兩個區間運算法,是表示值域的簡便寫法。
閉區間運算符
區間運算符(a...b)定義了 a 到 b 的區間範圍,包括 a 和 b 在內。
閉區間運算符在須要遍歷某區間內全部的值時頗有用,如在 for-in 循環中使用:
1 for index in 1...5 { 2 println("\(index) times 5 is \(index * 5)") 3 //輸出("\(index)乘以 5 得 (\index * 5)") 4 } 5 // 1 乘以 5 得 5 6 // 2 乘以 5 得 10 7 // 3 乘以 5 得 15 8 // 4 乘以 5 得 20 9 // 5 乘以 5 得 25
for-in 語句的更多介紹,詳見 流程控制 一章(後面章節譯到)。
半閉區間運算符
半閉區間運算符(a..b)定義了從 a 到 b 的區間,但 b 不包括在內。說它是半閉區間,是由於第一個值包含在區間內,但最後一個值在區間外。
半閉區間在處理從 0 開始計數的列表時有用,如遍歷數組,可從 0 數到列表的長度(但不包括長度值自己):
1 let names = ["Anna", "Alex", "Brian", "Jack"] 2 let count = names.count 3 for i in 0..count { 4 println("Person \(i + 1) is called \(names[i])") 5 } 6 // Person 1 名字是 Anna 7 // Person 2 名字是 Alex 8 // Person 3 名字是 Brian 9 // Person 4 名字是 Jack
注意,數組包含四個元素,但由於是半閉區間,因此 0..count 只數到 3(數組中最後一個元素的索引號)。數組更多信息詳見 數組 一章(後面章節譯到)。
邏輯運算符
邏輯運算符是對布爾邏輯值 true 或 false 的組合操做,Swift 支持 C 及其衍生語言的三種標準邏輯運算符:
· 邏輯非(!a)
· 邏輯與(a && b)
· 邏輯或(a || b)
邏輯非運算符
邏輯非運算符對布爾值取反,即 true 變成 false,false 變成true。
邏輯非運算符是一個前綴運算符,緊跟在所操做值的前面,沒有任何空格符。能夠理解爲"非",以下例:
1 let allowedEntry = false 2 if !allowedEntry { 3 println("ACCESS DENIED") 4 } 5 // prints "ACCESS DENIED" 6 //輸出」ACCESS DENIED「
代碼中的 if !allowedEntry 能夠理解爲「若是不容許進入」。隨後的下一行代碼僅當「不容許進入」成立時纔會執行;即 allowedEntry 爲 false 時才執行。
如上例,布爾值常量及變量的名稱應謹慎選擇命名,方可確保代碼簡明又具可讀性,同時也應避免使用雙重否認或引發混淆的邏輯語句。
邏輯與運算符
(a && b)構造這樣的邏輯表達式:運算符兩側的值均爲 true,整個表達式的求值結果才爲 true。
若是有一個值爲 false,整個表達式便爲 false。事實上,若是第一個值爲 false,第二個值將不執行求值運算,由於不管它爲什麼值,整個表達式的值都不可能等於 true。這也被稱爲短路求值(short-circuit evaluation)。
下面的例子驗證兩個值,當兩個值都爲 true 時才能訪問:
1 let enteredDoorCode = true 2 let passedRetinaScan = false 3 if enteredDoorCode && passedRetinaScan { 4 println("Welcome!") 5 } else { 6 println("ACCESS DENIED") 7 } 8 // prints "ACCESS DENIED" 輸出"ACCESS DENIED"
邏輯或運算符
(a || b)屬於中綴運算符,由兩個連續的豎線構成。它用來構造這樣的表達式:當兩個值中有一個爲 true時,整個表達式爲 true 。
與前面的邏輯與運算符同樣,邏輯或運算符在檢測它的兩個表達式時,也使用「短路求值」法。只要邏輯或表達式左側爲 true,其右側將不執行求值運算,由於這時右側的值對整個表達式的結果再也不有影響。
下例中,第一個 Bool 值(hasDoorKey)爲 false,但第二個值(knowOverridePassword)爲 true。由於有一個值爲 true,因此整個表達式的求值結果也爲 true,所以容許訪問:
1 let hasDoorKey = false 2 let knowsOverridePassword = true 3 if hasDoorKey || knowsOverridePassword { 4 println("Welcome!") 5 } else { 6 println("ACCESS DENIED") 7 } 8 // prints "Welcome!" 輸出"Welcome!"
組合使用邏輯運算符
能夠將多個邏輯運算符組合起來構成一個較長的複合表達式。
1 「if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword { 2 println("Welcome!") 3 } else { 4 println("ACCESS DENIED") 5 } 6 // prints "Welcome!" 輸出"Welcome!"
本例使用多個 && 及 || 運算符構成一條較長的複合表達式。不過,&& 與 || 運算符操做的仍然是兩個值,所以該組合表達式其實是由三個較短的表達式連立而成。它能夠這樣理解:
若是咱們輸入了正確的門禁密碼、而且經過了視網膜掃描;或者若是咱們有門鑰匙;或者若是咱們知道緊急的備用密碼,則容許訪問。
根據 enteredDoorCode、passedRetinaScan、hasDoorKey 三個常量推算,前兩個小表達式的值均爲 false。不過咱們知道緊急的備用密碼(knowsOverridePassword 爲 true),所以整個複合表達式的求值結果仍然爲 true。
顯式括號
有時(從語法來看)括號並非必需的,但加上括號卻頗有用,它可讓複雜表達式的易於閱讀。 在上例中,爲組合表達式的第一部分加上括號,可以使其意圖更明顯:
1 if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword { 2 println("Welcome!") 3 } else { 4 println("ACCESS DENIED") 5 } 6 // prints "Welcome!" //輸出"Welcome!"
括號將前兩個值與其餘值分隔開來,使其做爲總體邏輯中的一種可選狀態的意思更加明顯。組合表達式的結果不會改變,但對讀者而言,總體意圖更加清晰。可讀性老是優先於簡潔性;應儘量在合適的地方使用括號,使你的邏輯更加明晰。
謝謝,Swifter-QQ羣:362232993,同好者進~
Fork:https://github.com/Joejo/Swift-lesson-for-chinese