Basic Operators
操作符是一種用於檢查、操作、組合值的特殊的符號或短語。比如將兩個值相加(let i = 1 + 2)的加號(+)。更複雜的比如邏輯與(&&)、自增(++i:表示給i加上一個1後返回)。
Swift支援大多數標準C的操作符,而且為了消除錯誤增加了一些功能。為了與運算子(==)區分開來,賦值操作符(=)不返回任何值。算術運算子(+,-,*,/,% 等)檢測和避免值的溢出,在處理數字時,以免出現比儲存類型允許的值範圍大或小這些意想不到的結果。你可以使用在Overflow Operators描述的Swift溢出操作符來進行溢出值的展現。
與C不同的是,Swift在浮點數的計算中可以使用餘數(%)。Swift提供了2種網域作業符(a..<b和a...b)代表一系列值,而C中沒有這種操作符。
這一節中描述了Swift常用的操作符。而Advanced Operators一文中描述的是進階操作符,並描述了如何定義您自己的自訂動作符和如何繼承自己的自訂類型的標準操作符。
術語
操作符有一元、二元、三元: 一元操作符操作單個目標(比如-a).一元首碼操作符緊貼在他們的目標前(例如!b).一元尾碼操作符緊跟在他們的目標後(例如i++) 二元操作符操作目錄為2個。因為它們出現在目標中間所以稱為中綴 三元操作符操作目標為3個。和C一樣,Swift只有一個3元操作符:三元條件運算子(a?b:c)
操作符影響的值叫運算元,在運算式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 }
這種特性避免了賦值運算子(=)被當成等於運算子(==)的錯誤。因為if x=y是無效的,所以Swift有助於減少代碼中出現這種錯誤。
算術運算子
Swift為所有數字運算提供了4中算術運算子:加(+)減(-)乘(*)除(/).
1 + 2 // equals 3 5 - 3 // equals 2 2 * 3 // equals 6 10.0 / 2.5 // equals 4.0
與C和OC不同的是,Swift中的算術運算子預設情況下不允許值溢出。但是你可以選擇讓其可以溢出(a&+b),具體操作見 Overflow Operators一文。
加號(+)可用於字串的串連:
"hello, " + "world" // equals "hello, world"
兩個字元的值,一個字元和一個字串的值,可以通過加號形成一個新的string值。
其他詳情查看Concatenating Strings and Characters.一文。
取餘操作符
取餘操作符(a%b)計算出a可以容納多少個b,返回剩下的餘數。
注意取餘運算子在其他語言中稱為模數運運算元。嚴格來說,Swift中的取餘運算子在負數操作上要比模數運運算元更有意義。
下面的圖顯示了取餘操作符是如何工作的,為了計算9%4,你首先計算9中包含了多少個4.
很顯然,9中含有2個4.然後剩下1。在Swift中,可以寫成:
9 % 4 // equals 1
為了確定a%b的答案,取餘運算子(%)下面的方程式返回reminder作為它的結果輸出。
a = (b × some multiplier) + remainder
some multiplier的值為a所能包含b的個數的最大值。
將9和4放入上面的方程式中
9 = (4 × 2) + 1
當a的值是負數時,取餘運算子同樣適用。
-9 % 4 // equals -1
將-9和4放入方程式中
-9 = (4 × -2) + -1
得到餘數為-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,你可以不用在意傳回值。如果你想使用傳回值,要注意++和--的首碼和尾碼的區別。 如果操作符在變數前,那麼變數會先增加1或者減少1後再返回. 如果操作符在變數後,那麼變數會先返回然後再增加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
運算式a+=2實際上是a=a+2。事實上加號和等號就是組合到一個操作符進行加和賦值的運算。
注意複合運算子沒有傳回值,你不能寫成let c = a+=2.這和上面的提到的自增和自減效果是不一樣的
如果你想瞭解更多的複合運算操作符可以參見 Expressions. 一文。
比較子
Swift支援所有C的比較子。
等於(a==b) 不等於(a!=b) 大於(a>b) 小於(a<b) 大於等於(a>=b) 小於等於(a<=b)
注意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
比較子經常用於條件陳述式中,比如if語句:
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"
想看更多關於if語句的資訊,參考 Control Flow一文。
三元條件運算子
三元條件運算子是含有3部分的特殊運算子。其形式為question?answer1:answer2.它會根據questions得出的Bool值來選擇後面2個運算式之一來進行計算。如果question的值為true那麼就會選擇answer1來計算,反之選擇answer2來計算。
三元田間運算子類似下面的形式:
if question { answer1 } else { answer2 }
舉例說明:現在需要計算一個表中行的高度。要求是如果存在列名,行的高度要比內容高度高50個單位。如果不存在列名那麼行的高度就比內容高20個單位。
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
想瞭解更多關於for..in迴圈的,參考 Control Flow一文。
半封閉範圍運算子
半封閉運算子(a..<b)表示a到b範圍內的數,但是不包括b。叫它半封閉的原因是它包括第一個數但是不包含最後一個數。
當你用在數組這種以0為起始值的列表中,半封閉是很有用的。遍曆數組(不包括最後一個)是很方便的。
et names = ["Anna", "Alex", "Brian", "Jack"]let count = names.countfor 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
上面的數組包含4個元素,但是因為它是半封閉的0..<count只記數到3(數組中的最後一個數)。更多詳情,參考 Arrays一文。
但是實際代碼中發現a..<b這種方式並不正確,而a..b有半閉的效果。
<span style="color:#FF0000;">let a = 4for i in 0..a { println(i)}let b = 5for i in 0...b { println(i)}</span>
且a..b和a...b中間不要有空格,不然也會有問題
邏輯運算子
邏輯運算修改和組合邏輯值true和false.和C中的邏輯元素一樣,Swift也提供3中邏輯運算子。
邏輯非(!a) 邏輯與(a&&b) 邏輯或(a||b)
邏輯非
邏輯非(!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個值。運算式的輸出結果也不會因為加了括弧而發生變化,但是運算式變得易讀。易讀性優於簡潔性。使用括弧會使你的意圖更清晰。