Swift 4官方文檔中文版: Basic Operators(下)

Swift學(xué)習(xí)有問(wèn)必答群 : 313838956 . 本群由Guards翻譯組創(chuàng)建并維護(hù)
入群須知:

0.1 群主晚上每天20點(diǎn)--21點(diǎn)定時(shí)回答Swift相關(guān)的問(wèn)題.
0.2 群主會(huì)在看到問(wèn)題后, 第一時(shí)間回復(fù)
0.3 拒絕長(zhǎng)時(shí)間潛水, 拒絕討論和Swift , iOS 無(wú)關(guān)的問(wèn)題



該文章翻譯自Apple官方文檔: The Swift 4 Programming Language

Guards翻譯組 正在翻譯Swift 4的全套文檔, 這是該文檔第二章節(jié)《Basic Operators》的下半部分, 上半部分在這里,第一章節(jié)《The Basics》 上半部分請(qǐng)點(diǎn)這里/下半部分請(qǐng)點(diǎn)這里, 原文鏈接: Basic Operators

翻譯 : Jonhory (簡(jiǎn)書(shū) / GitHub)

校對(duì) : Stevin三天三夜 (Blog / GitHub)

譯者心聲

我們會(huì)不定期的更新翻譯文章, Guards翻譯組下周內(nèi)會(huì)發(fā)布 Strings and Characters 章節(jié)中文版. 如感興趣,可以關(guān)注我們的簡(jiǎn)書(shū)

我們是一群熱愛(ài)翻譯并且熱愛(ài) Swift 的人, 希望通過(guò)自己的努力讓不熟悉英語(yǔ)的程序員也能學(xué)習(xí)到國(guó)外的高質(zhì)量的文章. 如發(fā)現(xiàn)文章中翻譯錯(cuò)誤之處, 煩請(qǐng)跟我們聯(lián)系, 我們第一時(shí)間更正.

本篇包含內(nèi)容:

  • 空合運(yùn)算符
  • 區(qū)間運(yùn)算符
  • 邏輯運(yùn)算符

空合運(yùn)算符(Nil-Coalescing Operator)

空合運(yùn)算符a ?? b)會(huì)對(duì)可選類(lèi)型a嘗試解封,如果a包含一個(gè)值就進(jìn)行解封,如果anil則返回一個(gè)默認(rèn)值b。表達(dá)式a必須是一個(gè)可選(Optional)類(lèi)型。表達(dá)式b的類(lèi)型必須跟a存儲(chǔ)的值的類(lèi)型一致。

空合運(yùn)算符是對(duì)下面的代碼的簡(jiǎn)短表達(dá):

 a != nil ? a! : b 

上述代碼使用了三目運(yùn)算符。當(dāng)可選類(lèi)型a的值不為空時(shí),進(jìn)行強(qiáng)制解封(a!)以訪(fǎng)問(wèn)a的值,否則返回默認(rèn)值b。空合運(yùn)算符提供了一種更優(yōu)雅的方式去封裝條件判斷和解封兩種行為。

NOTE:

如果a為非空值(non-nil),那么值b不會(huì)進(jìn)行計(jì)算。這就是所謂的短路求值

下面的例子使用空合運(yùn)算符,實(shí)現(xiàn)了在默認(rèn)顏色名和可選自定義顏色名之間的選擇:

 let defaultColorName = "red"
 var userDefinedColorName: String?   // 默認(rèn)值為 nil

 var colorNameToUse = userDefinedColorName ?? defaultColorName
 // userDefinedColorName 值為 nil, 所以 colorNameToUse 值被設(shè)置為 "red"

userDefinedColorName變量被定義為一個(gè)可選的String類(lèi)型,默認(rèn)值為nil。因?yàn)?code>userDefinedColorName是一個(gè)可選類(lèi)型,你可以使用空合運(yùn)算符來(lái)判斷它的值。在上一個(gè)例子中,空合運(yùn)算符被用于初始化一個(gè)名為colorNameToUse字符串(String)類(lèi)型變量。因?yàn)?code>userDefinedColorName值為nil,所以表達(dá)式userDefinedColorName ?? defaultColorName會(huì)返回defaultColorName的值,即"red"

如果你分配一個(gè)非空值給userDefinedColorName,再次執(zhí)行空合運(yùn)算,運(yùn)算結(jié)果為userDefinedColorName解封之后的值而不是默認(rèn)值(defaultColorName)。

 userDefinedColorName = "green"
 colorNameToUse = userDefinedColorName ?? defaultColorName

 // userDefinedColorName 的值非 nil, 所以 colorNameToUse 的值被設(shè)置為 "green"

區(qū)間運(yùn)算符(Range Operators)

Swift 提供幾個(gè)方便表達(dá)一個(gè)區(qū)間的值的區(qū)間運(yùn)算符

閉區(qū)間運(yùn)算符

閉區(qū)間運(yùn)算符a...b)定義一個(gè)包含ab(包括ab)的所有值的區(qū)間。a的值不能超過(guò)b的值。

閉區(qū)間運(yùn)算符在遍歷一個(gè)區(qū)間的所有值時(shí)是非常有用的,如在for-in循環(huán)中:

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

關(guān)于for-in循環(huán),請(qǐng)查閱Control Flow

半開(kāi)區(qū)間運(yùn)算符

半開(kāi)區(qū)間運(yùn)算符a..<b)定了一個(gè)從ab但不包括b的區(qū)間。之所以被稱(chēng)為半開(kāi)區(qū)間運(yùn)算符,是因?yàn)樗ǖ谝粋€(gè)值但不包括最后一個(gè)值。如同閉區(qū)間運(yùn)算符,半開(kāi)間運(yùn)算符的a的值不能超過(guò)b的值。
如果ab的值相等,運(yùn)算范圍的結(jié)果將為空。

半開(kāi)區(qū)間運(yùn)算符在你使用一個(gè)從0開(kāi)始的列表(如數(shù)組)時(shí)尤其有效,非常方便地從0數(shù)到(但不包括)列表的長(zhǎng)度:

let names = ["Anna", "Alex", "Brian", "Jack"]
let count = names.count
for i in 0..<count {
    print("Person \(i + 1) is called \(names[i])")
}
// 第1個(gè)人叫 Anna
// 第2個(gè)人叫 Alex
// 第3個(gè)人叫 Brian
// 第4個(gè)人叫 Jack

注意這個(gè)數(shù)組有4個(gè)元素,但0..<count只數(shù)到3(該數(shù)組最后一個(gè)元素的下標(biāo)),因?yàn)樗前腴_(kāi)區(qū)間運(yùn)算符。關(guān)于數(shù)組,請(qǐng)查閱Arrays

單向區(qū)間

閉區(qū)間運(yùn)算符在某一個(gè)方向上的連續(xù)取值有另一種形式的表達(dá)——比如,一個(gè)包含所有數(shù)組元素的區(qū)間,從下標(biāo)2到數(shù)組的末尾。在這些情況下,你可以省略范圍運(yùn)算符一側(cè)的值。這種區(qū)間被稱(chēng)為單向區(qū)間是因?yàn)樵撨\(yùn)算符只需一側(cè)的值。如下:

for name in names[2...] {
    print(name)
}
// Brian
// Jack
 
for name in names[...2] {
    print(name)
}
// Anna
// Alex
// Brian

半開(kāi)區(qū)間運(yùn)算符在有最后的值的時(shí)候也有單向區(qū)間表達(dá)。就像你需要一個(gè)在范圍內(nèi)但不包括末尾的區(qū)間的時(shí)候。如下:

for name in names[..<2] {
    print(name)
}
// Anna
// Alex

單向區(qū)間可以在別的上下文中使用,不止是下標(biāo)。你不能遍歷省略第一個(gè)值的單向區(qū)間,因?yàn)椴幻鞔_從哪里開(kāi)始遍歷。你可以遍歷省略最終值的單向區(qū)間;然而,因?yàn)檫@個(gè)區(qū)間會(huì)無(wú)限循環(huán),請(qǐng)確保為該循環(huán)添加明確的結(jié)束條件。你可以檢查一個(gè)單向區(qū)間是否包含特定值,如下面的代碼所示。

let range = ...5
range.contains(7)   // false
range.contains(4)   // true
range.contains(-1)  // true

邏輯運(yùn)算符(Logical Operators)

邏輯運(yùn)算符的操作對(duì)象是邏輯布爾值。Swift 支持基于 C 語(yǔ)言的三個(gè)標(biāo)準(zhǔn)邏輯運(yùn)算符:

  • 邏輯非(!a
  • 邏輯與(a && b
  • 邏輯或(a || b
邏輯非運(yùn)算符

邏輯非運(yùn)算符!a)對(duì)一個(gè)布爾值取反,使truefalse,使falsetrue

邏輯非運(yùn)算符是一個(gè)前置運(yùn)算符,需要跟在操作數(shù)之前,且不加空格。讀作“非a”,例子如下:

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

語(yǔ)句if ! allowedEntry可以讀作“如果非allowedEntry”。接下一行代碼只有在“非allowedEntry”時(shí)為true,即allowedEntryfalse時(shí)被執(zhí)行。

在上述例子中,小心地選擇布爾常量或變量有助于代碼的可讀性,同時(shí)應(yīng)避免使用雙重邏輯非或混亂的邏輯語(yǔ)句。

邏輯與運(yùn)算符

邏輯與運(yùn)算符a && b)表達(dá)式只有在ab的值都為true時(shí),整個(gè)表達(dá)式才會(huì)是true

只要任一值為false,整個(gè)表達(dá)式的值為false。事實(shí)上,如果第一個(gè)值為false,則第二個(gè)值將不被運(yùn)算,因?yàn)樗豢赡苡绊懻麄€(gè)表達(dá)式的結(jié)果。這被稱(chēng)為*短路計(jì)算(short-circuit evaluation)*

如下例,只有兩個(gè)Bool值都true時(shí)才允許進(jìn)入if:

let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// 輸出 "ACCESS DENIED"
邏輯或運(yùn)算符

邏輯或運(yùn)算符a || b)是一個(gè)由兩個(gè)連續(xù)的|組成的中置運(yùn)算符。它表示了兩個(gè)邏輯表達(dá)式的其中一個(gè)值為true,整個(gè)表達(dá)式就為true

與邏輯與運(yùn)算符類(lèi)似,邏輯或運(yùn)算符也是“短路計(jì)算”的。當(dāng)左側(cè)的表達(dá)式為true時(shí),將不計(jì)算右側(cè)表達(dá)式,因?yàn)樗粫?huì)改變整個(gè)表達(dá)式的值。

在下面的例子中,第一個(gè)Bool值(hasDoorKey)為false,但第二個(gè)值(knowsOverridePassword)為true。因?yàn)槠渲幸粋€(gè)值為true,所以整個(gè)表達(dá)式為true,并且允許進(jìn)入:

let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// 輸出 "Welcome!"
邏輯運(yùn)算符組合計(jì)算

你可以組合多個(gè)邏輯運(yùn)算符來(lái)表達(dá)一個(gè)復(fù)合邏輯:

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

在這個(gè)例子中使用了多個(gè)&&||運(yùn)算符來(lái)創(chuàng)建一個(gè)長(zhǎng)復(fù)合邏輯表達(dá)式。然而,&&||運(yùn)算符始終只能操作兩個(gè)值,所以這實(shí)際上是三個(gè)簡(jiǎn)單邏輯連續(xù)操作的結(jié)果。我們來(lái)解讀一下:

如果我們輸入正確的密碼(enteredDoorCode)并通過(guò)了視網(wǎng)膜掃描(passedRetinaScan),或者有一個(gè)有效的鑰匙(hasDoorKey),又或者知道緊急情況下重置的密碼(knowsOverridePassword),我們就能把門(mén)打開(kāi)并進(jìn)入。

基于enteredDoorCodepassedRetinaScanhasDoorKey的值,前兩個(gè)簡(jiǎn)單邏輯的結(jié)果是false,但我們知道緊急情況下重置的密碼(knowsOverridePassword),所以整個(gè)表達(dá)式的值還是true

NOTE

Swift邏輯操作符&&||是左結(jié)合的,這意味著擁有多元邏輯操作符的復(fù)合表達(dá)式優(yōu)先計(jì)算最左邊的子表達(dá)式。

使用括號(hào)以明確優(yōu)先級(jí)

為了使一個(gè)復(fù)合表達(dá)式更易理解,有時(shí)使用括號(hào)來(lái)明確優(yōu)先級(jí)是有效的,即使它并不是必要的。在關(guān)于門(mén)的權(quán)限的例子中,給第一部分加上括號(hào),使它看起來(lái)邏輯更明確:

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

這個(gè)括號(hào)使前兩個(gè)值被看成整個(gè)邏輯表達(dá)式中獨(dú)立的一部分。雖然整個(gè)表達(dá)式的結(jié)果是一樣的,但對(duì)于讀代碼的人而言有括號(hào)的更易讀懂。可讀性比簡(jiǎn)潔性更重要,請(qǐng)?jiān)诳梢宰屇愦a變清晰的地方加個(gè)括號(hào)吧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,321評(píng)論 6 543
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,559評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 178,442評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,835評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,581評(píng)論 6 412
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,922評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,931評(píng)論 3 447
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 43,096評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,639評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,374評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,591評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,104評(píng)論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,789評(píng)論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,196評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,524評(píng)論 1 295
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,322評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,554評(píng)論 2 379

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