運算符 是可以檢查愁拭,修改或者組合值的特殊符號或者短語澎羞。例如,加法運算符(+
)將兩個數(shù)相加敛苇,像let i = 1 + 2
妆绞,邏輯與運算符組合兩個布爾值顺呕,像if enteredDoorCode && passedRetinaScan
。
Swift支持大多數(shù)標準C運算符并且改善了一些功能來避免常見的編碼錯誤括饶。賦值運算符(=
)不會返回一個值株茶,避免被錯誤的當成等于運算符(==
)使用。數(shù)學運算符(+
,-
,*
,/
,%
等等)會檢測并且不允許值溢出图焰,避免使用一些過大或者過小以致超出存儲它們的類型允許范圍的值而導致意外的結(jié)果启盛。可以通過使用Swift的溢出運算符來處理值溢出的情況技羔,詳見溢出運算符僵闯。
Swift同樣提供了兩個C沒有的區(qū)間運算符(a..<b
和a...b
),作為描述區(qū)間值的簡寫藤滥。
本章講述Swift的基礎運算符鳖粟。高級運算符章節(jié)會介紹Swift的高級運算符,并會介紹如何定義一個自定義運算符拙绊,以及為你的自定義類型實現(xiàn)運算符重載向图。
目錄
- 術(shù)語
- 賦值運算符
- 數(shù)學運算符
- 組合賦值運算符
- 比較運算符
- 三元條件運算符
- Nil聚合運算符
- 區(qū)間運算符
- 邏輯運算符
術(shù)語
運算符可以是一元,二元者三元的:
- 一元運算符作用于一個單獨對象(例如
-a
)标沪。一元前置運算符出現(xiàn)在對象的前面(例如!b
)榄攀,一元后置運算符出現(xiàn)在對象的后面(例如c!
)。 - 二元運算符作用于兩個對象金句,是中置的檩赢,因為它出現(xiàn)在兩個對象中間。
- 三元運算符作用于三個對象违寞。和C一樣漠畜,Swift只有一個三元運算符:三元條件運算符(
a ? b : c
)。
運算符影響的值稱為運算對象坞靶。在表達式1 + 2
中,符號+
是一個二元運算符蝴悉,它的兩個運算對象是值1
和2
彰阴。
賦值運算符
賦值運算符(a = b
)初始化或者更新a
的值為b
。
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幫助你避免了代碼中的這些錯誤。
數(shù)學運算符
Swift為所有的數(shù)值類型提供了四種標準的數(shù)學運算符:
- 加法(
+
) - 減法(
-
) - 乘法(
*
) - 除法(
/
)
1 + 2 // equals 3
5 - 3 // equals 2
2 * 3 // equals 6
10.0 / 2.5 // equals 4.0
和C與OC的數(shù)學運算符不同晃财,Swift的數(shù)學運算符默認是不允許值溢出的叨橱。可以使用Swift的溢出運算符來處理值溢出的情況(例如a &+ b
)。詳見溢出運算符罗洗。
加法運算符同樣適用于String
的拼接:
"hello, " + "world" // equals "hello, world"
取余運算符
取余運算符 (a % b
)會計算出b
的多少倍最接近a
愉舔,并返回剩余的值(也就是余數(shù))。
注意
取余運算符(%
)在其它語言中被稱作模運算符 伙菜。但是在Swift中對于負數(shù)的這種操作轩缤,嚴格來說是一個取余運算而不是一個模運算。
下面展示了取余運算符是如何工作的贩绕。為了計算9 % 4
火的,首先需要計算出4
的多少倍最接近9
。
你可以算出
4
的兩倍最接近9
淑倾,所以余數(shù)是1
(圖中橙色所示)馏鹤。在Swift中,可以寫成:
9 % 4 // equals 1
為了確定a % b
的答案踊淳,%
運算符計算以下的等式并返回remainder
作為輸出:
a = (b x some multiplier) + remainder
在這個等式中假瞬,some multiplier
是在滿足最接近a
的前提下b
的最大乘數(shù)。
將9
和4
帶入等式迂尝,結(jié)果如下:
9 = (4 x 2) + 1
同樣的方法也是用于當a
是一個負數(shù)時:
-9 % 4 // equals -1
將-9
和4
帶入等式脱茉,結(jié)果如下:
-9 = (4 x -2) + -1
得出余數(shù)為-1
。
當b
是負數(shù)時符號可忽略垄开,這意味著a % b
和a % -b
的結(jié)果總是一樣琴许。
一元負運算符
可以使用前綴-
確定一個數(shù)值型值的符號,它被稱為一元負運算符溉躲。
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
盡管+
實質(zhì)上什么都沒做箭券,但是當在代碼中使用了-
時,可以用+
提供對稱性疑枯。
組合賦值運算符
像C一樣辩块,Swift提供了組合賦值運算符 ,它將=
和其它運算符組合使用荆永。一個組合賦值運算符的例子是加等于運算符 (+=
)废亭。
var a = 1
a += 2
// a is now equal to 3
表達式a += 2
是a = a + 2
的簡寫。效率起見具钥,加法和賦值組合進一個運算符來同時執(zhí)行兩個操作豆村。
注意
組合賦值運算符并不返回一個值。例如骂删,不能寫成let b = a += 2
掌动。
想了解Swift標準庫提供的組合賦值運算符的完整列表四啰,詳見Swift標準庫運算符參考
比較運算符
Swift提供所有標準C的比較運算符:
- 等于(
a == b
) - 不等于(
a != b
) - 大于(
a >b
) - 小于(
a < b
) - 大等于(
a >= b
) - 小等于(
a <= b
)
注意
Swift同樣提供了兩個恒等運算符 (===
和!==
),他們用來檢查兩個對象指針是否指向了同一個對象實例坏匪。查看更多信息拟逮,詳見類和結(jié)構(gòu)體。
每個比較運算符都返回一個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".
想了解更多關于if
信息敦迄,詳見控制流。
你同樣也可以比較兩個有同樣數(shù)量值的元組凭迹,只要元組內(nèi)的每個值都是可比較的罚屋。例如Int
和String
是可以比較的,這意味著(Int, String)
類型的元組是可比較的嗅绸。與之相對脾猛,Bool
是不能比較的,所以包含布爾類型的元組是不可比較的鱼鸠。
元組從左到右逐一比較猛拴,直到找到兩個不同的值。這兩個值的比較結(jié)果作為整個元組的比較結(jié)果蚀狰。如果所有元素都相等愉昆,那么元組就相等。例如:
(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"
上例中麻蹋,從首行可以看到從左至右的比較方式跛溉。因為1
小于2
,所以(1, "zebra")
被認為小于(2, "apple")
扮授,忽略了元組的其它值芳室。無需關注"zebra"
小于"apple"
,因為比較結(jié)果已經(jīng)被元祖的第一個元素決定了刹勃。但是當元組的第一個元素相同時堪侯,第二個元素就會被比較 ,像2荔仁,3行那樣伍宦。
注意
Swift標準庫提供的元組比較運算符只支持元組元素個數(shù)小于7個的情況。當大等于7個時咕晋,需要自己實現(xiàn)比較運算符。
三元條件運算符
三元條件運算符 是一個由三部分組成的特殊運算符收奔,形式為question ? answer1 : answer2
掌呜。它是一個根據(jù)question
是否為真來選取兩個表達式其中之一的簡寫。如果為真坪哄,它選取answer1
并返回它的值质蕉,如果為假势篡,選取answer2
并返回它的值。
三元條件運算符是以下形式代碼的簡寫:
if question {
answer1
} else {
answer2
}
下面的例子用來計算table的行高模暗。如果這個行有頭部的話禁悠,行高要比contentHeight
高出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聚合運算符
nil聚合運算符 (a ?? b)會解包可選型a
濒旦,如果a
包含一個值的話,否則返回默認值b
再登。a
永遠是一個可選類型尔邓。b
必須符合a
存儲的數(shù)據(jù)類型。
nil聚合運算符是以下代碼的簡寫:
a != nil ? a! : b
以上代碼使用三元條件運算符锉矢,當a
不是nil
時梯嗽,強制解包(a!
)來獲取a
的解包值,否則返回b
沈撞。nil聚合運算符以一種簡潔和易讀的格式提供了一種更加優(yōu)雅的方式來包裝這種條件檢查和解包工作慷荔。
注意
如果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
的可選型的String
。因為userDefinedColorName
是一個可選類型壹士,你可以使用nil聚合運算符決定它的值磷雇。上面的例子中,這個運算符用來決定名為colorNameToUse
的String
型變量的值躏救。因為userDefinedColorName
是nil
唯笙,表達式userDefinedColorName ?? defaultColorName
返回defaultColorName
的值,依舊是“red”
如果userDefinedColorName
被賦一個非nil
值再次執(zhí)行nil聚合運算符檢查盒使,userDefinedColorName
解包的值會取代默認值被使用:
userDefinedColorName = "green"
colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName is not nil, so colorNameToUse is set to "green"
區(qū)間運算符
Swift提供兩種區(qū)間運算符崩掘,它們用來簡化描述值的范圍。
閉區(qū)間運算符
閉區(qū)間運算符 (a...b
)定義了一個從a
到b
少办,并且包括a
和b
的范圍苞慢。a
的值必須小于b
的值。
當遍歷一個范圍內(nèi)的所有值時英妓,閉區(qū)間運算符非常有用挽放,例如一個for-in
循環(huán):
or 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
查看更多for-in
信息绍赛,詳見控制流。
半開區(qū)間運算符
半開區(qū)間運算符 (a..<b
)定義了一個從a
到b
辑畦,但不包括b
的范圍吗蚌。之所以稱為半開 是因為它包括第一個值,但是不包含最后一個值纯出。和閉區(qū)間運算符一樣蚯妇,a
的值必須小于b
的值。如果a
的值等于b
的值潦刃,那么區(qū)間就是空的侮措。
當處理以0為基數(shù)的列表例如數(shù)組時,半開區(qū)間運算符是極其有用的乖杠,這里它可以計數(shù)到但是不包括列表的長度:
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
注意觀察數(shù)組包含4個元素分扎,但是0..<count
只計數(shù)到3
(最后一個元素的索引),因為它是一個半開區(qū)間胧洒。更多關于數(shù)組信息畏吓,詳見數(shù)組。
邏輯運算符
邏輯運算符 修改或者組合布爾邏輯值true
和false
卫漫。Swift支持基于C語言的三種標準邏輯運算符:
- 邏輯非(
!a
) - 邏輯與(
a && b
) - 邏輯或(
a || b
)
邏輯非運算符
邏輯非運算符 (!a
)轉(zhuǎn)換一個布爾值菲饼,因此true
變?yōu)?code>false,false
變?yōu)?code>true列赎。
邏輯非運算符是一個前置運算符宏悦,它會立刻出現(xiàn)在運算對象的前面,沒有任何空格包吝。他可以被解讀為“不是一個”饼煞,像下面例子所示:
let allowedEntry = false
if !allowedEntry {
print("ACCESS DENIED")
}
// Prints "ACCESS DENIED"
代碼片段if !allowedEntry
可以解讀為“如果不被允許進入”。接下來的代碼只會在“不允許進入”為真是執(zhí)行诗越。也就是說如果allowedEntry
為false
砖瞧。
如上例所示,慎重選擇布爾常量或者變量名有助于保持代碼的可讀性和簡潔性嚷狞,同樣的也要避免兩個負數(shù)或者令人疑惑的邏輯聲明块促。
邏輯與運算符
邏輯與運算符 (a && b
)創(chuàng)建一個邏輯表達式,表達式的兩個值必須都為true
才能保證整個表達式為true
床未。
如果任何一個值為false
竭翠,整個表達式也會為false
。實際上薇搁,如果第一個值為false
斋扰,那么第二個值不會被評估,因為它已經(jīng)不能讓整個表達式為true
了。這被稱作短路估值褥实。
下面的例子評估兩個Bool
值,只有在兩個值都為true
時才允許進入:
let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
print("Welcome!")
} else {
print("ACCESS DENIED")
}
// Prints "ACCESS DENIED"
邏輯或運算符
邏輯或運算符 (a || b
)是一個中置運算符裂允,它由兩個毗鄰的豎線構(gòu)成损离。當兩個值中的任何一個為真時,整個表達式就為真绝编。
同上面的邏輯與運算符一樣僻澎,邏輯或運算符使用短路評估計算表達式。如果一個邏輯表達式的左邊為true
十饥,右邊的表達式將不會計算窟勃,因為右邊的表達式已經(jīng)不能改變整個表達式的結(jié)果。
在下面的例子中逗堵,第一個Bool
值(hasDoorKey
)為false
秉氧,但是第二個值(knowsOverridePassword
)為true
。因為有一個值為true
蜒秤,所以整個表達式也被評估為true
汁咏,允許進入:
let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword {
print("Welcome!")
} else {
print("ACCESS DENIED")
}
// Prints "Welcome!"
組合邏輯運算符
你可以組合多個邏輯運算符創(chuàng)建一個更長的組合表達式:
if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
print("Welcome!")
} else {
print("ACCESS DENIED")
}
// Prints "Welcome!"
這個例子使用多個&&
和||
運算符創(chuàng)建了一個更長的組合表達式。但是作媚,&&
和||
運算符仍然只作用于兩個值攘滩,因此實際上是三個更小的表達式鏈接在了一起。這個例子可以解讀為:
如果我們輸入了正確的房間密碼并且通過了高清掃描纸泡,或者我們有一個合法的房門鑰匙漂问,或者我們知道緊急重置密碼,那么就能打開房門女揭。
根據(jù)enteredDoorCode
蚤假,passedRetinaScan
和hasDoorKey
的值,前兩個子表達式是false
田绑,但是勤哗,我們知道緊急重置密碼,所以整個組合表達式仍然是true
掩驱。
注意
Swift的邏輯運算符&&
和||
是左結(jié)合的芒划,也就是說包含多個邏輯運算符的復合表達式會首先評估最左邊的子表達式。
清晰的括號
有時為了使一個復雜的表達式易讀欧穴,引入括號是很有用的即使它們并不真的需要民逼。在上面進入房間的例子中,為第一個組合表達式添加括號來使意圖明確是很有用的:
if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {
print("Welcome!")
} else {
print("ACCESS DENIED")
}
// Prints "Welcome!"
這個括號使得前兩個值被看成整個邏輯中不同的可能狀態(tài)的一部分涮帘。組合表達式的結(jié)果并沒有改變拼苍,但是整個意圖變得清晰易讀。易讀性總是優(yōu)先于簡潔性;使用括號來使你的意圖明確疮鲫。
上一篇:Swift-基礎部分
下一篇:Swift-字符串和字符