swift官方推薦翻譯文檔之基本運算符

運算符是檢查、改變、合併值的特殊符號或短語。例如,加號+將兩個數相加(如let i = 1 + 2)。更復雜的運算例子包括邏輯與運算符&&(如if enteredDoorCode && passedRetinaScan),或讓 i 值加1的便捷自增運算符++i等。html

Swift 支持大部分標準 C 語言的運算符,且改進許多特性來減小常規編碼錯誤。如:賦值符(=)不返回值,以防止把想要判斷相等運算符(==)的地方寫成賦值符致使的錯誤。算術運算符(+-*/%等)會檢測並不容許值溢出,以此來避免保存變量時因爲變量大於或小於其類型所能承載的範圍時致使的異常結果。固然容許你使用 Swift 的溢出運算符來實現溢出。詳情參見溢出運算符swift

區別於 C 語言,在 Swift 中你能夠對浮點數進行取餘運算(%),Swift 還提供了 C 語言沒有的表達兩數之間的值的區間運算符(a..<ba...b),這方便咱們表達一個區間內的數值。數組

本章節只描述了 Swift 中的基本運算符,高級運算符包含了高級運算符,及如何自定義運算符,及如何進行自定義類型的運算符重載。ide


術語

運算符有一元、二元和三元運算符。ui

  • 一元運算符對單一操做對象操做(如-a)。一元運算符分前置運算符和後置運算符,前置運算符需緊跟在操做對象以前(如!b),後置運算符需緊跟在操做對象以後(如i++)。編碼

  • 二元運算符操做兩個操做對象(如2 + 3),是中置的,由於它們出如今兩個操做對象之間。lua

  • 三元運算符操做三個操做對象,和 C 語言同樣,Swift 只有一個三元運算符,就是三目運算符(a ? b : c)。spa

受運算符影響的值叫操做數,在表達式1 + 2中,加號+是二元運算符,它的兩個操做數是值12code


賦值運算符

賦值運算(a = b),表示用b的值來初始化或更新a的值:htm

let b = 10
var a = 5
a = b
// a 如今等於 10


若是賦值的右邊是一個多元組,它的元素能夠立刻被分解成多個常量或變量:

let (x, y) = (1, 2)
// 如今 x 等於 1, y 等於 2

與 C 語言和 Objective-C 不一樣,Swift 的賦值操做並不返回任何值。因此如下代碼是錯誤的:

if x = y {
    // 此句錯誤, 由於 x = y 並不返回任何值
}

這個特性使你沒法把(==)錯寫成(=),因爲if x = y是錯誤代碼,Swift幫你避免此類錯誤的的發生。


算術運算符

Swift 中全部數值類型都支持了基本的四則算術運算:

  • 加法(+

  • 減法(-

  • 乘法(*

  • 除法(/

1 + 2       // 等於 3
5 - 3       // 等於 2
2 * 3       // 等於 6
10.0 / 2.5  // 等於 4.0

與 C 語言和 Objective-C 不一樣的是,Swift 默認狀況下不容許在數值運算中出現溢出狀況。可是你可使用 Swift 的溢出運算符來實現溢出運算(如a &+ b)。詳情參見溢出運算符

加法運算符也可用於String的拼接:

"hello, " + "world"  // 等於 "hello, world"

求餘運算符

求餘運算(a % b)是計算b的多少倍剛恰好能夠容入a,返回多出來的那部分(餘數)。

注意:
求餘運算(%)在其餘語言也叫取模運算。然而嚴格說來,咱們看該運算符對負數的操做結果,"求餘"比"取模"更合適些。


咱們來談談取餘是怎麼回事,計算9 % 4,你先計算出4的多少倍會恰好能夠容入9中:Art/remainderInteger_2x.png

2倍,很是好,那餘數是1(用橙色標出)

在 Swift 中能夠表達爲:

9 % 4    // 等於 1

爲了獲得a % b的結果,%計算了如下等式,並輸出餘數做爲結果:

a = (b × 倍數) + 餘數

倍數取最大值的時候,就會恰好能夠容入a中。

94代入等式中,咱們得1

9 = (4 × 2) + 1

一樣的方法,咱們來計算 -9 % 4

-9 % 4   // 等於 -1

-94代入等式,-2是取到的最大整數:

-9 = (4 × -2) + -1

餘數是-1

在對負數b求餘時,b的符號會被忽略。這意味着 a % ba % -b的結果是相同的。

浮點數求餘計算

不一樣於 C 語言和 Objective-C,Swift 中是能夠對浮點數進行求餘的。

8 % 2.5   // 等於 0.5

這個例子中,8除於2.5等於30.5,因此結果是一個Double0.5Art/remainderFloat_2x.png

自增和自減運算

和 C 語言同樣,Swift 也提供了對變量自己加1或減1的自增(++)和自減(--)的縮略算符。其操做對象能夠是整形和浮點型。

var i = 0
++i      // 如今 i = 1

每調用一次++ii的值就會加1。實際上,++ii = i + 1的簡寫,而--ii = i - 1的簡寫。

++--既能夠用做前置運算又能夠用做後置運算。++ii++--ii--都是有效的寫法。

咱們須要注意的是這些運算符便可修改了i的值也能夠返回i的值。若是你只想修改i的值,那你就能夠忽略這個返回值。但若是你想使用返回值,你就須要留意前置和後置操做的返回值是不一樣的,她們遵循如下原則:

  • ++前置的時候,先自増再返回。

  • ++後置的時候,先返回再自增。

例如:

var a = 0
let b = ++a // a 和 b 如今都是 1
let c = a++ // a 如今 2, 但 c 是 a 自增前的值 1

上述例子,let b = ++a先把a加1了再返回a的值。因此ab都是新值1

let c = a++,是先返回了a的值,而後a才加1。因此c獲得了a的舊值1,而a加1後變成2。

除非你須要使用i++的特性,否則推薦你使用++i--i,由於先修改後返回這樣的行爲更符合咱們的邏輯。

一元負號運算符

數值的正負號可使用前綴-(即一元負號)來切換:

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

一元負號(-)寫在操做數以前,中間沒有空格。

一元正號運算符

一元正號(+)不作任何改變地返回操做數的值:

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

雖然一元+什麼都不會改變,但當你在使用一元負號來表達負數時,你可使用一元正號來表達正數,如此你的代碼會具備對稱美。

組合賦值運算符(Compound Assignment Operators)

如同 C 語言,Swift 也提供把其餘運算符和賦值運算(=)組合的組合賦值運算符,組合加運算(+=)是其中一個例子:

var a = 1
a += 2 // a 如今是 3

表達式a += 2a = a + 2的簡寫,一個組合加運算就是把加法運算和賦值運算組合成進一個運算符裏,同時完成兩個運算任務。

注意:
複合賦值運算沒有返回值,let b = a += 2這類代碼是錯誤。這不一樣於上面提到的自增和自減運算符。

比較運算符

全部標準 C 語言中的比較運算均可以在 Swift 中使用:

  • 等於(a == b

  • 不等於(a != b

  • 大於(a > b

  • 小於(a < b

  • 大於等於(a >= b

  • 小於等於(a <= b

注意: Swift 也提供恆等===和不恆等!==這兩個比較符來判斷兩個對象是否引用同一個對象實例。更多細節在類與結構

每一個比較運算都返回了一個標識表達式是否成立的布爾值:

1 == 1   // true, 由於 1 等於 1
2 != 1   // true, 由於 2 不等於 1
2 > 1    // true, 由於 2 大於 1
1 < 2    // true, 由於 1 小於2
1 >= 1   // true, 由於 1 大於等於 1
2 <= 1   // false, 由於 2 並不小於等於 1

比較運算多用於條件語句,如if條件:

let name = "world"
if name == "world" {
    print("hello, world")
} else {
    print("I'm sorry \(name), but I don't recognize you")
}
// 輸出 "hello, world", 由於 `name` 就是等於 "world"

關於if語句,請看控制流

三目運算符(Ternary Conditional Operator)

三目運算符的特殊在於它是有三個操做數的運算符,它的原型是 問題 ? 答案1 : 答案2。它簡潔地表達根據問題成立與否做出二選一的操做。若是問題成立,返回答案1的結果; 若是不成立,返回答案2的結果。

三目運算符是如下代碼的縮寫形式:

if question {
    answer1
} else {
    answer2
}

這裏有個計算表格行高的例子。若是有表頭,那行高應比內容高度要高出50點;若是沒有表頭,只需高出20點:

let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50 : 20)
// rowHeight 如今是 90

上面的寫法比下面的代碼更簡潔:

let contentHeight = 40
let hasHeader = true
var rowHeight = contentHeight
if hasHeader {
    rowHeight = rowHeight + 50
} else {
    rowHeight = rowHeight + 20
}
// rowHeight 如今是 90

第一段代碼例子使用了三目運算,因此一行代碼就能讓咱們獲得正確答案。這比第二段代碼簡潔得多,無需將rowHeight定義成變量,由於它的值無需在if語句中改變。

三目運算提供有效率且便捷的方式來表達二選一的選擇。須要注意的事,過分使用三目運算符會使簡潔的代碼變的難懂。咱們應避免在一個組合語句中使用多個三目運算符。

空合運算符(Nil Coalescing Operator)

空合運算符(a ?? b)將對可選類型a進行空判斷,若是a包含一個值就進行解封,不然就返回一個默認值b.這個運算符有兩個條件:

  • 表達式a必須是Optional類型

  • 默認值b的類型必需要和a存儲值的類型保持一致

空合運算符是對如下代碼的簡短表達方法

a != nil ? a! : b

上述代碼使用了三目運算符。當可選類型a的值不爲空時,進行強制解封(a!)訪問a中值,反之當a中值爲空時,返回默認值b。無疑空合運算符(??)提供了一種更爲優雅的方式去封裝條件判斷和解封兩種行爲,顯得簡潔以及更具可讀性。

注意: 若是a爲非空值(non-nil),那麼值b將不會被估值。這也就是所謂的短路求值。

下文例子採用空合運算符,實現了在默認顏色名和可選自定義顏色名之間抉擇:

let defaultColorName = "red"
var userDefinedColorName: String?   //默認值爲 nil

var colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName 的值爲空,因此 colorNameToUse 的值爲 "red"

userDefinedColorName變量被定義爲一個可選String類型,默認值爲nil。因爲userDefinedColorName是一個可選類型,咱們可使用空合運算符去判斷其值。在上一個例子中,經過空合運算符爲一個名爲colorNameToUse的變量賦予一個字符串類型初始值。 因爲userDefinedColorName值爲空,所以表達式userDefinedColorName ?? defaultColorName返回defaultColorName的值,即red

另外一種狀況,分配一個非空值(non-nil)給userDefinedColorName,再次執行空合運算,運算結果爲封包在userDefaultColorName中的值,而非默認值。

userDefinedColorName = "green"
colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName 非空,所以 colorNameToUse 的值爲 "green"

區間運算符

Swift 提供了兩個方便表達一個區間的值的運算符。

閉區間運算符

閉區間運算符(a...b)定義一個包含從ab(包括ab)的全部值的區間,b必須大於等於a。 ‌ 閉區間運算符在迭代一個區間的全部值時是很是有用的,如在for-in循環中:

for index in 1...5 {
    print("\(index) * 5 = \(index * 5)")
}
// 1 * 5 = 5
// 2 * 5 = 10
// 3 * 5 = 15
// 4 * 5 = 20
// 5 * 5 = 25

關於for-in,請看控制流

半開區間運算符

半開區間(a..<b)定義一個從ab但不包括b的區間。 之因此稱爲半開區間,是由於該區間包含第一個值而不包括最後的值。

半開區間的實用性在於當你使用一個從0開始的列表(如數組)時,很是方便地從0數到列表的長度。

let names = ["Anna", "Alex", "Brian", "Jack"]
let count = names.count
for i in 0..<count {
    print("第 \(i + 1) 我的叫 \(names[i])")
}
// 第 1 我的叫 Anna
// 第 2 我的叫 Alex
// 第 3 我的叫 Brian
// 第 4 我的叫 Jack

數組有4個元素,但0..<count只數到3(最後一個元素的下標),由於它是半開區間。關於數組,請查閱數組

邏輯運算

邏輯運算的操做對象是邏輯布爾值。Swift 支持基於 C 語言的三個標準邏輯運算。

  • 邏輯非(!a

  • 邏輯與(a && b

  • 邏輯或(a || b

邏輯非

邏輯非運算(!a)對一個布爾值取反,使得truefalsefalsetrue

它是一個前置運算符,需緊跟在操做數以前,且不加空格。讀做非 a,例子以下:

let allowedEntry = false
if !allowedEntry {
    print("ACCESS DENIED")
}
// 輸出 "ACCESS DENIED"

if !allowedEntry語句能夠讀做「若是非 allowedEntry。」,接下一行代碼只有在「非 allowedEntry」爲true,即allowEntryfalse時被執行。

在示例代碼中,當心地選擇布爾常量或變量有助於代碼的可讀性,而且避免使用雙重邏輯非運算,或混亂的邏輯語句。

邏輯與

邏輯與(a && b)表達了只有ab的值都爲true時,整個表達式的值纔會是true

只要任意一個值爲false,整個表達式的值就爲false。事實上,若是第一個值爲false,那麼是不去計算第二個值的,由於它已經不可能影響整個表達式的結果了。這被稱作「短路計算(short-circuit evaluation)」。

如下例子,只有兩個Bool值都爲true的時候才容許進入:

let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// 輸出 "ACCESS DENIED"

邏輯或

邏輯或(a || b)是一個由兩個連續的|組成的中置運算符。它表示了兩個邏輯表達式的其中一個爲true,整個表達式就爲true

同邏輯與運算相似,邏輯或也是「短路計算」的,當左端的表達式爲true時,將不計算右邊的表達式了,由於它不可能改變整個表達式的值了。

如下示例代碼中,第一個布爾值(hasDoorKey)爲false,但第二個值(knowsOverridePassword)爲true,因此整個表達是true,因而容許進入:

let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// 輸出 "Welcome!"

邏輯運算符組合計算

咱們能夠組合多個邏輯運算來表達一個複合邏輯:

if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// 輸出 "Welcome!"

這個例子使用了含多個&&||的複合邏輯。但不管怎樣,&&||始終只能操做兩個值。因此這實際是三個簡單邏輯連續操做的結果。咱們來解讀一下:

若是咱們輸入了正確的密碼並經過了視網膜掃描,或者咱們有一把有效的鑰匙,又或者咱們知道緊急狀況下重置的密碼,咱們就能把門打開進入。

前兩種狀況,咱們都不知足,因此前兩個簡單邏輯的結果是false,可是咱們是知道緊急狀況下重置的密碼的,因此整個複雜表達式的值仍是true

注意: Swift 邏輯操做符&&||是左結合的,這意味着擁有多元邏輯操做符的複合表達式優先計算最左邊的子表達式。

使用括號來明確優先級

爲了一個複雜表達式更容易讀懂,在合適的地方使用括號來明確優先級是頗有效的,雖然它並不是必要的。在上個關於門的權限的例子中,咱們給第一個部分加個括號,使它看起來邏輯更明確:

if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// 輸出 "Welcome!"

這括號使得前兩個值被當作整個邏輯表達中獨立的一個部分。雖然有括號和沒括號的輸出結果是同樣的,但對於讀代碼的人來講有括號的代碼更清晰。可讀性比簡潔性更重要,請在可讓你代碼變清晰的地方加個括號吧!

相關文章
相關標籤/搜索