Swift-基礎運算符

運算符 是可以檢查愁拭,修改或者組合值的特殊符號或者短語澎羞。例如,加法運算符(+)將兩個數(shù)相加敛苇,像let i = 1 + 2妆绞,邏輯與運算符組合兩個布爾值顺呕,像if enteredDoorCode && passedRetinaScan
Swift支持大多數(shù)標準C運算符并且改善了一些功能來避免常見的編碼錯誤括饶。賦值運算符(=)不會返回一個值株茶,避免被錯誤的當成等于運算符(==)使用。數(shù)學運算符(+,-,*,/,%等等)會檢測并且不允許值溢出图焰,避免使用一些過大或者過小以致超出存儲它們的類型允許范圍的值而導致意外的結(jié)果启盛。可以通過使用Swift的溢出運算符來處理值溢出的情況技羔,詳見溢出運算符僵闯。
Swift同樣提供了兩個C沒有的區(qū)間運算符(a..<ba...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中,符號+是一個二元運算符蝴悉,它的兩個運算對象是值12彰阴。

賦值運算符

賦值運算符(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ù)。
94帶入等式迂尝,結(jié)果如下:
9 = (4 x 2) + 1
同樣的方法也是用于當a是一個負數(shù)時:

-9 % 4   // equals -1

-94帶入等式脱茉,結(jié)果如下:
-9 = (4 x -2) + -1
得出余數(shù)為-1
b是負數(shù)時符號可忽略垄开,這意味著a % ba % -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 += 2a = 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)的每個值都是可比較的罚屋。例如IntString是可以比較的,這意味著(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聚合運算符決定它的值磷雇。上面的例子中,這個運算符用來決定名為colorNameToUseString型變量的值躏救。因為userDefinedColorNamenil唯笙,表達式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)定義了一個從ab少办,并且包括ab的范圍苞慢。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)定義了一個從ab辑畦,但不包括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ù)組

邏輯運算符

邏輯運算符 修改或者組合布爾邏輯值truefalse卫漫。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í)行诗越。也就是說如果allowedEntryfalse砖瞧。
如上例所示,慎重選擇布爾常量或者變量名有助于保持代碼的可讀性和簡潔性嚷狞,同樣的也要避免兩個負數(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蚤假,passedRetinaScanhasDoorKey的值,前兩個子表達式是false田绑,但是勤哗,我們知道緊急重置密碼,所以整個組合表達式仍然是true掩驱。

注意
Swift的邏輯運算符&&||是左結(jié)合的芒划,也就是說包含多個邏輯運算符的復合表達式會首先評估最左邊的子表達式。

清晰的括號

有時為了使一個復雜的表達式易讀欧穴,引入括號是很有用的即使它們并不真的需要民逼。在上面進入房間的例子中,為第一個組合表達式添加括號來使意圖明確是很有用的:

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

這個括號使得前兩個值被看成整個邏輯中不同的可能狀態(tài)的一部分涮帘。組合表達式的結(jié)果并沒有改變拼苍,但是整個意圖變得清晰易讀。易讀性總是優(yōu)先于簡潔性;使用括號來使你的意圖明確疮鲫。

上一篇:Swift-基礎部分
下一篇:Swift-字符串和字符

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吆你,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子俊犯,更是在濱河造成了極大的恐慌妇多,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件燕侠,死亡現(xiàn)場離奇詭異者祖,居然都是意外死亡,警方通過查閱死者的電腦和手機绢彤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門七问,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人茫舶,你說我怎么就攤上這事械巡。” “怎么了饶氏?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵坟比,是天一觀的道長。 經(jīng)常有香客問我嚷往,道長葛账,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任皮仁,我火速辦了婚禮籍琳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贷祈。我一直安慰自己趋急,他們只是感情好,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布势誊。 她就那樣靜靜地躺著呜达,像睡著了一般。 火紅的嫁衣襯著肌膚如雪粟耻。 梳的紋絲不亂的頭發(fā)上查近,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音挤忙,去河邊找鬼霜威。 笑死,一個胖子當著我的面吹牛册烈,可吹牛的內(nèi)容都是我干的戈泼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼大猛!你這毒婦竟也來了扭倾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤挽绩,失蹤者是張志新(化名)和其女友劉穎吆录,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體琼牧,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年哀卫,在試婚紗的時候發(fā)現(xiàn)自己被綠了巨坊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡此改,死狀恐怖趾撵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情共啃,我是刑警寧澤占调,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站究珊,受9級特大地震影響纵苛,放射性物質(zhì)發(fā)生泄漏攻人。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望猿棉。 院中可真熱鬧铺根,春花似錦乔宿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锣杂。三九已至,卻和暖如春元莫,著一層夾襖步出監(jiān)牢的瞬間踱蠢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工苇侵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留企锌,地道東北人撕攒。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓打却,卻偏偏與公主長得像,于是被迫代替她去往敵國和親猿推。 傳聞我的和親對象是個殘疾皇子蹬叭,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 術(shù)語 運算符有單目饥悴,雙目盲再,和三目 單目運算符:作用在一個目標上瓣铣,他可以寫在目標的前面(-a)答朋,也可以寫在目標的后面...
    Joker_King閱讀 768評論 0 0
  • 由蘋果官網(wǎng)翻譯得來fork自https://github.com/letsswift/The-Swift-Prog...
    佛祖拿屠刀閱讀 417評論 0 1
  • 關于 Swift 重要這個文檔所包含的準備信息, 是關于開發(fā)的 API 和技術(shù)的棠笑。這個信息可能會改變, 根據(jù)這個文...
    無灃閱讀 4,301評論 1 27