Swift語言指南(二)基礎操作符

來源:互聯網
上載者:User

標籤:swift

操作符是用於檢測、更改或者組合值的特殊符號或短語。例如,加法操作符 (+) 將兩個數字加到一起 (如 let i = 1 + 2)。更複雜的例子包括邏輯與操作符 && (如 if enteredDoorCode && passedRetinaScan) 和自增操作符 ++i,就是把 i 的值加1的捷徑。

Swift 支援大多數標準的C 操作符並且改善了幾項功能以消除常見的編碼錯誤。賦值操作符 (=) 不傳回值,是為了防止想用等於操作符(==)時不小心用成了賦值操作符。算數運算子 (+, -, *, /, % 等等) 檢測並禁止值溢出,以免運算時得出的結果大於或小於類型允許的範圍。你可以用 Swift 的溢出運算子來做溢出操作,詳情見《溢出操作符》一節。

不像C,Swift 可以對浮點數進行取餘操作 (%) 。 Swift 還提供兩個範圍操作符 (a..<b 和 a…b) ,這在C裡是沒有的,用來表示一個範圍的值。

這一章講述 Swift 裡的常用操作符。《進階操作符》一節涵蓋了Swift 的進階操作符,講述了如何自訂動作符以及如何?自訂類型的標準操作符。

術語

操作符分一元、二元和三元:

一元操作符操作於一個單一目標(如 -a)。一元首碼操作符在它們的目標之前緊跟出現(如 !b),一元尾碼操作符在它們的目標之後緊跟出現(如 i++)。
二元操作符操作於兩個目標(如 2 + 3),是中綴操作符,因為它出現在兩個目標的中間。
三元操作符操作於三個目標。像 C 一樣,Swift 只有一個三元操作符,就是三元條件操作符 (a ? b : c)。
操作符影響的值稱為運算元。在運算式 1 + 2 中,符號 + 是一個二元操作符,它的運算元是值 1 和 2。

賦值操作符

賦值操作符 (a = b) 用 b 的值初始化或更新 a 的值:

let b = 10var a = 5a = b// a 現在等於 10

如果賦值操作符的右邊是一個有多個值的元組,它的元素可以馬上被拆解為多個常量或變數:

let (x, y) = (1, 2)// x 等於 1,而且 y 等於 2

不像 C 和 Objective-C 裡的賦值操作符,Swift 裡的賦值操作符自身並不傳回值。下面的語句是不行的:

if x = y {    // 這是無效的,因為 x = y 並不傳回值}

這個特性防止了賦值操作符 (=) 被誤用作等於操作符 (==) 。Swift 幫你避免 if x = y 這些錯誤在代碼裡出現。

算術運算子

Swift 對數字類型支援四種標準的算術運算子:

加 (+)
減 (-)
乘 (*)
除 (/)

1 + 2       // 等於 35 - 3       // 等於 22 * 3       // 等於 610.0 / 2.5  // 等於 4.0

不像 C 和 Objective-C 裡的算術運算子,Swift 算術運算子預設不允許值溢出。你可以用 Swift 的溢出操作符(如 a &+ b)來選擇值溢出操作。更多內容見《溢出操作符》一節。

加操作符還支援字串串連:

"hello, " + "world"  // 等於 "hello, world"
取餘操作符

取餘操作符 (a % b) 計算的是 a 是 b 的幾個倍數,並返回剩餘的部分 (就是餘數)。

注意

取餘操作符 (%) 在其它語言裡也稱為模數操作符。不過,在Swift 裡對負數的操作,嚴格來說是取餘而不是模數。

這是取餘操作符如何工作的例子。要計算 9 % 4,先算出9最多可以包括多少個4:

9裡最多有兩個4,餘數是1 (上面的橙色部分).

Swift 裡,這個可以寫作:

9 % 4    // 等於 1

要得出 a % b 的答案, % 操作符計算以下等式並返回 remainder 作為它的輸出:

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 的負數值負號會被忽略掉。這就是說 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++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或減1再傳回值。
如果操作符寫在變數後,那麼先傳回值再加1或減1。
例如:

var a = 0let b = ++a// a 和 b 現在都等於 1let c = a++// a 現在等於 2, 但 c 被設為加之前的值 1

在上例中, let b = ++a 在傳回值前增加 a 的值。這就是為什麼 a 和 b 都等於新的值 1。

但是, let c = a++ 在傳回值以後再增加 a 的值。這就是說 c 得到了舊的值 1,而 a 更改為等於2。

除非需要特別使用 i++,否則推薦你都用 ++i 和 –i ,因為這個更符合修改 i 和返回結果的典型預期行為。

一元減操作符

數字值的符號可以用首碼 - 進行切換,也就是一元減操作符:

let three = 3let minusThree = -three       // minusThree 等於 -3let plusThree = -minusThree   // plusThree 等於 3, 或者 "負 負 三"

一元減操作符 (-) 直接加在要操作的值之前,不加任何空格。

一元加操作符

一元加操作符 (+) 只是簡單地返回所操作的值,不作任何改變:

let minusSix = -6let alsoMinusSix = +minusSix  // alsoMinusSix 等於 -6

雖然一元加操作符實際上不幹任何事,但是在既有負數又有正數的時候可以讓你的代碼看起來更對稱一點。

複合賦值操作符

像 C 那樣,Swift 也提供複合賦值操作符,將複製符 (=) 和其它操作結合起來。一個例子就是加賦值操作符 (+=):

var a = 1a += 2// a 現在等於 3

運算式 a += 2 是 a = a + 2 的縮寫。加和賦值結合到一個操作符可以同時執行兩個操作。

注意

複合操作符不傳回值。不能這麼寫 let b = a += 2。這個和上面提到的加和減操作符不同。

《運算式》一節裡有全部的複合賦值操作符介紹。

比較操作符

Swift 支援所有標準的 C 比較操作符:

等於 (a == b)
不等於 (a != b)
大於 (a > b)
小於 (a < b)
大於或等於 (a >= b)
小於或等於 (a <= b)

注意

Swift 還提供了兩個恒等操作符 (=== 和 !==),用來測試兩個對象引用是否都引用同一個對象執行個體。更多資訊,請參考《類與結構體》一章。

每一個比較操作符都返回一個布爾值,指示語句是否為true:

1 == 1   // true, 因為 1 等於 12 != 1   // true, 因為 2 不等於 12 > 1    // true, 因為 2 大於 11 < 2    // true, 因為 1 小於 21 >= 1   // true, 因為 1 大於或等於 12 <= 1   // false, 因為 2 不小於或等於 1

比較操作符通常用在條件陳述式,比如 if 語句裡:

let name = "world"if name == "world" {    println("hello, world")} else {    println("I‘m sorry \(name), but I don‘t recognize you")}// 列印出 "hello, world", because name is indeed equal to "world"

要瞭解更多關於 if 語句的資訊,參見《控制流程》一章。

三元條件操作符

三元條件操作符分三個部分,形式是這樣的 question ? answer1 : answer2。根據 question 是 true 還是 false 來返回那兩個運算式中的一個。如果 question 是 true,返回 answer1 ;否則,返回 answer2 。

三元條件操作符是以下代碼的簡寫:

if question {    answer1} else {    answer2}

這是一個計算表格行高的例子。如果行有表頭的話,行高應該比內容的高度高50個點,如果沒有表頭,高20個點:

let contentHeight = 40let hasHeader = truelet rowHeight = contentHeight + (hasHeader ? 50 : 20)// rowHeight 等於 90

前面的例子是以下代碼的縮寫:

let contentHeight = 40let hasHeader = truevar rowHeight = contentHeightif hasHeader {    rowHeight = rowHeight + 50} else {    rowHeight = rowHeight + 20}// rowHeight 等於 90

第一個例子裡,三元條件操作符的使用表示 rowHeight 可以在一行代碼裡就設定上正確的值。這比第二個例子簡潔得多,而且不需要把 rowHeight 定義為變數,因為它的值沒有必要在 if 語句裡變更。

三元條件操作符為決定使用兩個運算式中哪一個提供了高效的縮寫。但是,使用三元條件操作符的時候要小心。濫用的話,雖然簡潔,但會讓你的代碼不好讀懂。盡量避免將多個三元條件操作符合并到一條複合陳述式中。

Nil 合併作業符

nil 合併作業符 (a ?? b) 如果a有值則開啟可選項a,否則如果a是 nil 返回 b 的值。運算式 a 都是可選類型。運算式 b 必須匹配a裡儲存的類型。

nil 合并運算子是以下例子的縮寫:

a != nil ? a! : b

上例使用三元條件操作符並強制開啟 (a!) 併當a不為nil時訪問a裡的值,否則返回b。 nil 合併作業符提供了封裝這個條件檢測和開啟的一種更高雅的方式,而且形式更簡潔和可讀性更高。

注意

如果a的值是非nil的,b不會被求值。這就是所謂的短路求值。

以下的例子使用 nil 合併作業符從預設顏色名和可選的使用者自訂色彩名之間做選擇:

let defaultColorName = "red"var userDefinedColorName: String?   // 預設為 nilvar colorNameToUse = userDefinedColorName ?? defaultColorName// userDefinedColorName 是 nil,所以 colorNameToUse 被設定為預設的 "red"

userDefinedColorName 變數被定義為一個可選的 String ,預設值為 nil 。因為 userDefinedColorName 是一個可選類型,你可以用 nil 合併作業符來得到它的值。在上例中,操作符用來檢測名為 colorNameToUse 的 String 的初始值。由於 userDefinedColorName 是 nil,所以運算式 userDefinedColorName ?? defaultColorName 返回 defaultColorName 的值 “red”。

如果你把一個非nil的值設定給 userDefinedColorName 並執行 nil 合併作業符再次檢測的話,那麼 userDefinedColorName 裡的值就會被使用,而不是預設的那個了:

userDefinedColorName = "green"colorNameToUse = userDefinedColorName ?? defaultColorName// userDefinedColorName 不是 nil, 所以 colorNameToUse 被設定為 "green"
範圍操作符

Swift 包括兩個範圍操作符,表示一個範圍的值的縮寫。

閉合範圍操作符

閉合範圍操作符 (a…b) 定義了一個從 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 迴圈,參見《控制流程》一章。

半開範圍操作符

半開範圍操作符 (a..<b) 定義了一個從a到b的範圍,但是不包括b。因為只包括第一個值,不包括最後那個值,所以稱為半開。和閉合範圍操作符一樣,a的值不能大於b。

半開範圍特別適用於從0開始的列表,如數組,一直數到(但不包括)列表的長度:

let 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

注意數組包含了四個項,不過 0..<count 只數到3 (就是數組的最後一個索引), 因為它是一個半開範圍。關於數組的更多資訊,參見《數組》一節。

邏輯操作符

邏輯操作符用於修改或合并布爾邏輯值true和false。Swift 支援基於C語言的三種標準的邏輯操作符:

邏輯否 (!a)邏輯與 (a && b)邏輯或 (a || b)
邏輯否操作符

邏輯否操作符 (!a) 將一個布爾值取反操作,true變false,false變true。

邏輯否操作符是一個首碼操作符,在其操作的值之前立即出現,沒有空格。它可以讀作 “不是 a”, 如下例所示:

let allowedEntry = falseif !allowedEntry {    println("ACCESS DENIED")}// 列印出 "ACCESS DENIED"

短語 if !allowedEntry 可以讀作 “如果不允許進入” 。如果“不允許進入”是true,後續代碼才會執行;也就是如果 allowedEntry 是 false。

正如在這個例子裡所說,謹慎使用布爾常量和變數名可以協助保持代碼的可讀性和簡潔性,而避免雙重否定或混亂的邏輯語句。

邏輯與操作符

邏輯與操作符 (a && b) 建立邏輯運算式,只有兩個值都是true時整個運算式的值才為true。

如果其中一個值是false,整個運算式也會是false。實際上,第一個值是false的話,都不會再看第二個值,因為不可能會使整個運算式等於true的。這就是所謂的短路取值。

這個例子檢測兩個Bool 值,並且只有兩個值都是true的時候才允許訪問:

let enteredDoorCode = truelet passedRetinaScan = falseif enteredDoorCode && passedRetinaScan {    println("Welcome!")} else {    println("ACCESS DENIED")}// 列印出 "ACCESS DENIED"
邏輯或操作

邏輯或操作 (a || b) 是一個中綴操作符,位於兩個相鄰的字元之間。用它來建立的運算式只要其中一個值為true,那整個運算式的值都為true。

如上面的邏輯與操作符一樣,邏輯或操作符也使用短路取值。如果邏輯與左邊的運算式是true,右邊的部分就不用看了,因為不管怎樣都不會改變整個運算式的輸出。

在下面的例子中,第一個Bool值I (hasDoorKey) 是 false,不過第二個值 (knowsOverridePassword) 是 true。由於其中一個值是true,所以整個運算式的值就是true,允許訪問:

let hasDoorKey = falselet knowsOverridePassword = trueif hasDoorKey || knowsOverridePassword {    println("Welcome!")} else {    println("ACCESS DENIED")}// 列印出 "Welcome!"
邏輯操作符的結合

你可以將多個邏輯操作符結合起來以建立更長的複合運算式:

if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {    println("Welcome!")} else {    println("ACCESS DENIED")}// 列印出 "Welcome!"

這個例子使用了多個 && 和 || 操作符來建立一個更長的複合運算式。然而, && 和 || 操作符仍然只操作與兩個值,所以這其實是三個更小的運算式串在一起。這個例子可以讀作:

如果我們進入了正確的門並通過了視網膜掃描,或者我們有一把有效門鑰匙,或者我們知道緊急替代密碼,那就可以允許訪問。

基於 enteredDoorCode, passedRetinaScan, 和 hasDoorKey 的值,頭兩個小運算式是false。不過,知道了緊急替代密碼,所以整個複合運算式仍然為true。

顯示的括弧

有時候加上括弧也是很有用的,雖然比不是嚴格要求必須要有,但可以使複雜的運算式更容易讀懂。在上面的門禁例子裡,在複合運算式的第一部分加上括弧就很有用了:

if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {    println("Welcome!")} else {    println("ACCESS DENIED")}// 列印出 "Welcome!"

加了括弧就很明顯的能看出前兩個值是作為整個邏輯的一個獨立部分的。複合運算式的輸出並沒改變,但整個運算式的意圖更容易讀懂了。相比簡潔性,可讀性更受青睞;用括弧就可以讓你代碼的意思更明了。

Swift語言指南(二)基礎操作符

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.