運算符是用于檢查、更改或組合值的特殊符號或短語。例如,加法運算符(+)添加兩個數字,如let i = 1 + 2,邏輯運算符(&&)組合兩個布爾值,如if enteredDoorCode && passedRetinaScan。
Swift支持大多數標準的C操作符,并改進了一些功能來消除常見的編碼錯誤。賦值運算符(=)不返回值,以防止在使用equal to運算符(==)時錯誤地使用它。算術運算符(+、-、*、/、%等)檢測和禁止值溢出,以避免在處理大于或小于存儲它們的類型的允許值范圍的數字時出現意外結果。您可以選擇使用Swift的溢出操作符來評估溢出行為,如Overflow Operators中所述。
Swift還提供了C語言中沒有的范圍操作符,比如a..< b和a…作為表示值范圍的快捷方式。
本章描述了Swift中的常用操作符。
Advanced Operators 包括Swift的高級運算符,并描述如何定義您自己的自定義運算符,以及為您自己的自定義類型實現標準運算符。
Terminology 術語
運算符有一元、二元或三元:
- 一元運算符只操作一個目標(例如-a)。一元前綴操作符緊接在目標的前面(如!b),一元后綴操作符緊接在目標的后面(如c!)。
- 二進制操作符操作兩個目標(例如2 + 3),并且是中綴,因為它們出現在兩個目標之間。
- 三元操作符操作三個目標。和C語言一樣,Swift只有一個三元運算符,即三元條件運算符(a ?b: c)。
操作符影響的值是操作數。在表達式1 + 2中,+符號是一個二進制操作符,它的兩個操作數是值1和2。
Assignment Operator 賦值運算符
賦值運算符(a = b)用b的值初始化或更新a的值:
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 {
...
}
該特性可以防止在實際使用等于操作符(==)時意外使用賦值操作符(=)。通過使if x = y無效,Swift可以幫助您避免代碼中的此類錯誤。
Arithmetic Operators 算數運算符
Swift支持所有數字類型的四種標準算術運算符:
- 加(+)
- 減(-)
- 乘(*)
- 除(/)
1 + 2 // equals 3
5 - 3 // equals 2
2 * 3 // equals 6
10.0 / 2.5 // equals 4.0
與C和Objective-C中的算術運算符不同,Swift算術運算符默認情況下不允許值溢出。您可以選擇使用Swift的溢出操作符(如a &+ b)來評估溢出行為。
加法運算符也支持字符串連接:
"hello, " + "world" // equals "hello, world"
Remainder Operator 余數運算符
余數運算符(a % b)計算出b在a中的倍數,并返回剩余的值(稱為余數)。
注意:余數運算符(%)在其他語言中也稱為模運算符。然而,它在負數中的Swift行為意味著,嚴格地說,它是余數,而不是模運算。
Unary Minus Operator 一元-操作符
數值的符號可以使用前綴-來切換,稱為一元減運算符:
let three = 3
let minusThree = -three // minusThree equals -3
let plusThree = -minusThree // plusThree equals 3, or "minus minus three"
一元減號運算符(-)直接前綴在它所作用的值之前,沒有任何空格。
Unary Plus Operator
一元+操作符
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的簡寫。實際上,加法和賦值被合并到一個操作符中,該操作符同時執行兩個任務。
注意:復合賦值操作符不返回值。例如,你不能讓b = a += 2。
有關Swift標準庫提供的操作符的信息,請閱讀 Operator Declarations。
Comparison Operators 比較運算符
- 等于 (a == b)
- 不等于 (a != b)
- 大于 (a > b)
- 小于 (a < b)
- 大于等于 (a >= b)
- 小于等于 (a <= b)
注意:Swift還提供了兩個標識符(===和!==),用于測試兩個對象引用是否同時引用同一個對象實例。
每個比較運算符返回一個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" {
print("hello, world")
} else {
print("I'm sorry \(name), but I don't recognize you")
}
// Prints "hello, world", because name is indeed equal to "world".
如果兩個元組具有相同的類型和相同數量的值,則可以對它們進行比較。從左到右比較元組,每次一個值,直到比較發現兩個不相等的值。比較這兩個值,比較的結果決定了元組比較的總體結果。如果所有元素都相等,那么元組本身也是相等的。例如:
(1, "zebra") < (2, "apple") // true because 1 is less than 2; "zebra" and "apple" are not compared
(3, "apple") < (3, "bird") // true because 3 is equal to 3, and "apple" is less than "bird"
(4, "dog") == (4, "dog") // true because 4 is equal to 4, and "dog" is equal to "dog"
只有當操作符可以應用于各自元組中的每個值時,才可以將元組與給定的操作符進行比較。例如,如下面的代碼所示,您可以比較類型(String, Int)的兩個元組,因為可以使用<操作符比較String和Int值。相反,類型(String, Bool)的兩個元組不能與<操作符進行比較,因為<操作符不能應用于Bool值。
("blue", -1) < ("purple", 1) // OK, evaluates to true
("blue", false) < ("purple", true) // Error because < can't compare Boolean values
注意:Swift標準庫包含了少于7個元素的元組比較,如果你的元組元素大于等于7,需要比較時,您必須自己實現比較操作符。
Ternary Conditional Operator 三元條件運算符
question ? answer1 : answer2
如果question為真,則計算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
let rowHeight: Int
if hasHeader {
rowHeight = contentHeight + 50
} else {
rowHeight = contentHeight + 20
}
// rowHeight is equal to 90
第一個例子使用三元條件運算符意味著rowHeight可以在一行代碼中設置為正確的值,這比第二個例子中使用的代碼更簡潔。
三元條件運算符為決定要考慮哪一個表達式提供了一種有效的簡寫。但是,要小心使用三元條件運算符。如果過度使用,它的簡潔性可能導致難以閱讀的代碼。避免將三元條件運算符的多個實例合并到一個復合語句中。
Nil-Coalescing Operator nil 聚合運算符
nil 聚合運算符 (a ?? b) 如果可選類型a有一個值,那么將其展開值返回,如果a為nil則返回b,表達式a總是可選類型。表達式b必須匹配存儲在a中的類型。
nil 聚合運算符是以下代碼的縮寫:
a != nil ? a! : b
注意 : 如果a的值是非nil的,則不計算b的值。這就是所謂的短路計算。
下面的例子使用nil 聚合運算符在默認顏色名和可選的用戶定義顏色名之間進行選擇:
let defaultColorName = "red"
var userDefinedColorName: String? // defaults to nil
var colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName is nil, so colorNameToUse is set to the default of "red"
如果您為userDefinedColorName分配一個非空值,并再次執行nil-coalescing操作符檢查,則使用包裝在userDefinedColorName中的值,而不是默認值:
userDefinedColorName = "green"
colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName is not nil, so colorNameToUse is set to "green"
Range Operators 區間運算符
Swift包含幾個范圍操作符,它們是表示值范圍的快捷方式。
Closed Range Operator 閉區間運算符
閉區間運算符(a…b)定義了一個從a到b的范圍,包括值a和b。a的值不能大于b。
閉區間運算符在遍歷希望使用所有值的范圍時非常有用,例如for-in循環:
for index in 1...5 {
print("\(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
Half-Open Range Operator 半開區間運算符
半開區間運算符(a..<b) 與閉區間運算符一樣,a的值不能大于b。如果a的值等于b,那么得到的值域將是空的。
半開區間運算符在處理從零開始的列表(如數組)時特別有用,在數組中計算列表的長度(但不包括)非常有用:
let names = ["Anna", "Alex", "Brian", "Jack"]
let count = names.count
for i in 0..<count {
print("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開始的。
One-Sided Ranges 單邊區間運算符
區間一遍有限制,另一邊達到所有符合的值。
for name in names[2...] {
print(name)
}
// Brian
// Jack
for name in names[...2] {
print(name)
}
// Anna
// Alex
// Brian
for name in names[..<2] {
print(name)
}
// Anna
// Alex
單邊區間可以用于其他上下文中,而不僅僅是下標。不能在忽略第一個值的單邊區間內迭代,因為不清楚迭代應該從哪里開始。您可以在一個忽略其最終值的單邊區間內迭代;但是,由于范圍無限地繼續,請確保為循環添加顯式結束條件。還可以檢查單側范圍是否包含特定值,如下面的代碼所示。
let range = ...5
range.contains(7) // false
range.contains(4) // true
range.contains(-1) // true
Logical Operators 邏輯運算符
邏輯運算符修改或組合布爾邏輯值true和false。Swift支持基于c語言的三種標準邏輯操作符:
- 邏輯非(!a)
- 邏輯與 (a && b) a和b同時為true,才返回true
- 邏輯或 (a || b) 或者,只要一個滿足,就返回true
邏輯非運算符
邏輯NOT操作符是一個前綴操作符,它出現在它操作的值之前,沒有任何空格。如下例所示:
let allowedEntry = false
if !allowedEntry {
print("ACCESS DENIED")
}
// Prints "ACCESS DENIED"
邏輯與 運算符
let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
print("Welcome!")
} else {
print("ACCESS DENIED")
}
// Prints "ACCESS DENIED"
邏輯或 運算符
let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword {
print("Welcome!")
} else {
print("ACCESS DENIED")
}
// Prints "Welcome!"
組合邏輯運算符
您可以組合多個邏輯運算符來創建更長的復合表達式:
if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
print("Welcome!")
} else {
print("ACCESS DENIED")
}
// Prints "Welcome!"
注意:Swift邏輯運算符&&和||是左關聯的,這意味著具有多個邏輯運算符的復合表達式首先計算最左邊的子表達式。
Explicit Parentheses 明確的括號
有時候,在不嚴格需要括號的情況下,添加括號是很有用的,這樣可以使復雜表達式的意圖更易于閱讀。在上面的door access例子中,在復合表達式的第一部分添加括號是很有用的,可以使其意圖顯式:
if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {
print("Welcome!")
} else {
print("ACCESS DENIED")
}
// Prints "Welcome!"
圓括號清楚地表明,前兩個值被認為是整個邏輯中獨立的可能狀態的一部分。復合表達式的輸出沒有變化,但是總體意圖對讀者來說更清晰。可讀性總是優先于簡潔;用括號來幫助你明確你的意圖。