Swift4.1 第二章 Basic Operators

基本運算符

一個運算符是一個特殊的字符或短語,你能夠用它來檢查,改變,合併值。例如:加號(+)表示兩個數相加,例如let i = 1 + 2。還有邏輯運算符 AND (&&)用來關聯兩個布爾值,例如:if enteredDoorCode && passedRetinaScanhtml

Swift支持大多數標準的C語言的操做符,而且改進了許多特性用來減小常規的編譯錯誤。操做符=不意味着返回一個值,這是爲了和賦值運算符==進行區分,避免由於錯寫爲=出現錯誤。算數運算符(+,-,*,/ 等)會檢測並不容許值的溢出,這主要是用來避免由於值過大或者太小而超出它的類型所承載的範圍致使異常的結果。你可使用swift溢出的運算符來實現溢出,具體請參照溢出運算符git

Swiftc語言不一樣的是,swift提供了區間運算符。例如:a..<ba...b,這方便咱們表達一個區間內的數值。github

這個小節描述了Swift中的基本操做符,高級運算符會包含Swift中的高級運算符,以及如何進行自定義運算符和如何用你本身的方式來實現標準的操做符。swift

術語

運算符分爲一元,二元和三元運算符。數組

  • 一元運算符是對單一目標進行操做的(例如-a)。一元運算符有前綴和或追之分,前綴運算符每每出如今操做對象的前面(例如!b),後綴運算符每每出如今操做對象的後面 (例如:c!)
  • 二元運算符是操做對象是兩個目標,運算符的位置在操做對象的中間(例如:a+b)。
  • 三元運算符的操做對象是三個目標,和c語言同樣,swift只有一個三元運算符,就是三目運算符(a?b:c)。

    受操做符影響的值叫操做者。在表達式1+2中,操做符+是一個二元運算符,它的兩個操做者的值是12app

賦值運算符

賦值運算符用於初始化和更新ab的值(例:a=b)。ide

let b = 10
var a = 5
a = b
// 如今a的值爲10

若是賦值運算符的右邊是一個具備多值的元組,那麼它的成員能夠被當即分解成多個常量和變量。ui

let (x, y) = (1,2)
//  x的值爲1  y的值爲2

賦值運算符在swift中和在Objective-C以及C語言中是不一樣的,賦值運算符在swift中不會返回一個值。下面的語句是不合法的:spa

if x = y {
    // 這是不合法的,由於等式 x = y沒有返回值。
}

Swift中的這個特性避免了在使用等式運算符(==)中由於誤用賦值運算符(=)而致使的錯誤。當語句if x = y 不合法的時候,swift會在你的代碼中提示你避免出現這樣的錯誤。翻譯

算術運算符

swift爲全部的數字類型提供了四種標準的算術運算符。

  • 加號運算符(+)
  • 減號運算符(-)
  • 乘號運算符(*)
  • 除號運算符(/)
1 + 2 // 等於3
5 - 3 // 等於2
2 * 3 // 等於6
10.0 / 2.5 // 等於4.0

Objective-CC語言不一樣的是,Swift的算術運算符不容許值超出默認範圍。可是你可使用Swift的溢出運算符來進行值溢出的運算。(例:a &+ b),具體請參見溢出運算符
加號運算符一樣使用於字符串的拼接:

"hello," + 「world」 // 等價於hello,world

求餘運算符

求餘運算符(a%b)是計算b的多少倍恰好能夠放下a,而後返回一個多出來的值(也就是求餘數)。(好比:4%2 餘數爲0,3%2 餘數爲1)。

注意:
求餘運算符(%)在其餘語言中也就作求模運算符。然而嚴格來講,在swift中這個操做符是對於負數來講的,這裏叫作求餘比求模更加貼切。

這裏給你們講一下求餘運算符是怎麼工做的。計算9%4,首先你要計算出4的多少倍可以放得下9

求餘運算

你能夠發現4的多少倍可以放得下9,餘數爲1(橘色展現的就是)

在Swift中,求餘是這樣寫的:

9 % 4 // 等於1

爲了計算出a%b的值,操做符%用下面的等式來計算並返回了餘數做爲輸出。

a = (b * 倍數) + 餘數

倍數是b的一個很大的倍數的時候,可以放的下a

94 帶入等式之後:

9 = (4 * 2) + 1

當a的值爲負數的時候,計算餘數的方法一樣適應:

-9 % 4 // 等於1

餘數的值爲-1
在對b求餘的時候,b的符號能夠被忽略掉,這就是說a % ba % -b 結果是同樣的。

一元負號運算符

數值類型正負能夠用在前面加-來進行轉換,這就是所謂的一元負號運算符。

let three = 3
let minusThree  = -three// 等價於 -3
let plusThree = -minusThree // 等價於3

一元負號運算符在使用的時候,直接加載常量和變量以後,他們之間不須要添加空格。

一元加號運算符

當一元加號運算符使用的時候,操做符返回的值是他自己,沒有發生任何改變。

let minusSix = -6
let  alsoMinusSix = +minusSix
//alsoMinusSix 的值仍爲-6

儘管一元加號運算符在使用的時候沒有什麼實際意義,可是在你使用一元負號來表示負數的時候,能夠用一元加號來表示一個正數,這樣會使你的代碼看起來對稱。

組合運算符

和C語言同樣,Swift也提供了組合運算符用(=)和其餘操做符的組合。下面是一個加號的組合運算符:

var a = 1
a += 2 // 這裏a的值爲3
print("aa value is \(a)")

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

注意:
組合運算符不會返回一個值,例如:你不能這樣寫:let b = a += 2

關於更多swift標準操做符的問題,請查看運算符聲明

比較運算符

Swift支持全部標準的C語言比較符。

  • 相等(a == b)
  • 不相等(a != b)
  • 大於(a > b)
  • 小於(a < b)
  • 大於等於(a >= b)
  • 小於等於(a <= b)

注意:
Swift也提供了兩個操做符 恆等和不恆等(=== and !==)用這兩個操做符你能夠判斷兩個對象是否引用同一個實體實例。瞭解更多請參照類與結構體

每個比表運算符都會返回一個布爾值表示這個表達式是否是對的。

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 知足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語句的用法,請參看控制流

若是兩個元組的類型相同而且有相同個數的子元素,那麼這兩個元組能夠用來比較。元組從左到右一個值一個值的進行比較,直到發現有兩個不一樣的值爲止。在進行比較的過程當中,若是元組中每一個元素都相同,那麼咱們能夠說這兩個元組相等。例如:

(1,"zebra") < (2,"apple") //返回true 由於1比2小,"zebra"和"apple"是不能被比較的
(3,"apple") < (3,"bird") // 返回true 由於3 等於 3,"apple" 比"bird"少
(4,"dog") < (4,"dog") // 返回true,由於4 等於4 「dog」和「dog」相同。

在上面的這個例子中,你能夠看到從左到右的比較行爲出如今第一行。由於12小,(1,"zebra")已經被認爲比(2,"apple")小了,無論元組的其餘值,因此"zebra">"apple"對結果沒有影響,由於在比較的時候元組的第一個元素就已經把結果定了。不過當第一個元素相等的時候,就會對第二個第三個元素進行比較了。

當元素的每一個元素都可以用操做符進行比較的時候,咱們能夠對元組進行比較。例如:在下面的代碼中你能夠對兩個(String,Int)類型的元組進行比較,由於StringInt均可以用操做符<進行比較。相反,(String,Bool)類型的元組不能用操做符<進行比較,由於Bool不能用操做符<進行比較。

("blue",-1) < ("purple",1)// OK ,返回結果爲true
("blue",false) < ("purple",true)//Binary operator '<' cannot be applied to two '(String, Bool)' operands 布爾類型的值不能進行比較(自己比較已是true和false了。。再進行比較,過度了啊)

注意:
Swift標準庫裏是包含元素小於7個的元組之間的比較的。若是要比較超過7個元素的元組的話,你必須本身實現比較的操做符。

三元運算符

三元運算符是一個特殊的操做符是由三個操做數組成,好比:question?answer1:answer2這種形式。這個是基於questiontrue仍是false的一種表達。若是questiontrue那麼它的返回answer1的值,不然,返回answer2的值。

三元運算符的簡寫以下:

//let  question = true
//let answer1 = "333"
//let answer2 = "333"
//print("the answer is \(question ? answer1:answer2)")
if question {
    answer1
} else {
    answer2
}

這裏有一個計算表格行的高度的例子。題意大概是這樣的,內容的高度是固定的,當這一行有表頭的話高度加50若是沒有表頭的話加20。

let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50:20)// 結果爲90

上面的這個語句是下面的語句的簡寫:

let contentHeight = 40
let hasHeader = true
let rowHeight:Int
if hasHeader {
    rowHeight = contentHeight + 50
} else {
    rowHeight = contentHeight + 20
}
// rowHeight 結果爲90

在第一個例子中,用的是三元操做運算符意味着rowHeight一行低嗎就能獲得正確的值,這比第二個例子的代碼更加簡潔。

三元條件運算符提供了一個高效的判斷兩個參數表達式的標準,須要注意的是,過分的使用三元運算符會使簡潔的代碼看的不容易懂。咱們應該避免在一個組合的語句中使用多個三元運算符。

合併空值運算符

合併空值運算符(a ?? b)對可選類型a若是包含一個值的時候被打開,或者當a的值爲空(nil)的時候返回一個默認的值b。表達式a也是一個可選類型。默認值b的類型必需要和a所存儲的值的類型保持一致(也就是說既然ba的默認值,那麼b的值的類型就必須和a保持一致,這纔是默認值的意義所在,若是a沒值那麼默認值就頂上來)。

合併空值運算符最簡單的代碼表達式這樣的:

a != nil ? a!  : b

上面的示例代碼中使用了三元運算符,當可選類型a不爲空的時候,強制打開a(a!),訪問a的值,反之,返回默認值b。合併空值運算符提供了一個更加優雅的方式來對條件進行判斷和封裝,這增長了代碼的簡潔性和易讀性。

注意:
若是a的值是非空的時候,b的值永遠不會被使用。這也就是所謂的短路求值。

下面的例子採用的合併空值運算符實現了在默認顏色和可選自定義顏色中進行選擇。

let defaultColorName = "red"
var userDefinedColorName: String?//默認值是nil
var colorNameToUse = userDefinedColorName ?? defaultColorName
// 由於userDefinedColorName是nil,因此colorNameToUse被設置爲默認值"red"

變量userDefinedColorName定義的是默認值爲nil的可選的變量,由於變量userDefinedColorName是可選的類型,所以你可使用合併空值運算符來空值它的值。在上面的例子中,操做符被用來決定一個字符串變量colorNameToUse的默認值。由於userDefinedColorName的值爲空,表達式userDefinedColorName ?? defaultColorName返回了defaultColorName也就是"red"

若是你給userDefinedColorName賦一個非空的值,而後讓合併空值運算符來檢查一下,那麼userDefinedColorName的值就會替換掉默認值。

userDefinedColorName = "green"
var colorNameToUse = userDefinedColorName ?? defaultColorName // 由於userDefinedColorName 不爲空,因此colorNameToUse的值爲"green"。

區間運算符

Swift包含了幾個區間運算符,他們表示了一個範圍的值的便捷方式。

閉區間運算符

閉區間運算符(a...b)定義了一個只能在ab之間的運行範圍,它包括邊界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

瞭解更多關於for-in信息,請參看控制流

半開區間運算符

半開區間運算符(a ..< b)定義了一個能在ab之間運行的範圍,可是不包括b。也就是說,半開區間包括了它的首值,但不包括尾值(也就是說是半開半閉區間)。和閉區間操做符同樣,a的值老是小於b的。若是a的值和b的值相同,那麼結果區間就是空的。

當你在處理從0開始的數組的時候,半開運算符顯得頗有用,它從0開始遍歷到數組的長度(可是不包含數組的長度)。

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

咱們能夠觀察到,數組包括四個元素,可是0 ..< count僅包括到3(數組的最後一個元素的索引),由於這是半開半閉區間。關於更多數組相關信息,請查看數組

單側運算符

閉區間有另一種形式讓區間朝着一個方向儘量長的延伸。例如:一個包含全部數組元素的區間,從索引爲2的地方開始到數組的結束。在這種狀況下,你能夠省略掉操做符一邊的值。由於操做符僅一邊有值,因此它叫作單側區間。例如:

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

邏輯運算符

邏輯運算符的操做對象是邏輯布爾值(true or false),Swift基於C語言的三種邏輯表達式。

  • 邏輯非(!a)
  • 邏輯與(a && b)
  • 邏輯或 (a || b)

邏輯非運算符

邏輯非運算符是對一個布爾值取反,就是讓true變成false,讓false變成true
邏輯非運算符是一個前置運算符,它每每出如今操做值的前面,不須要添加空格。它能夠被讀做非a,下面是一個例子:

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

//打印結果是ACCESS DENIED

表達語句if !allowedEntry能夠被讀做「若是不容許進入」。下面一行代碼只有在「不容許進入」是true,也就是說只有在allowedEntryfalse的時候執行。

在這個例子中,當心的選擇布爾常量和變量有助於咱們保持代碼的可讀性,而且避免了雙重邏輯非運算符,或者混亂的邏輯語句。

邏輯與運算符

邏輯表達式與運算(a && b)表示的是隻有等式兩邊同時爲true的時候,才爲true,不然就是false
若是有任意一個爲false,那麼整個表達式就是false。事實上,若是第一個表達式爲false的時候,第二個表達式就不執行了,由於這個時候已經不能保證整個表達式是true了,這被稱爲短路計算。
下面的例子中,只有當兩個判斷是中的值都爲true的時候,if語句纔會執行。

let enterDoorCode = true
let passedRetainScan = false
if enterDoorCode && passedRetainScan {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
//打印結果是ACCESS DENIED

邏輯或運算符

邏輯或運算符是由兩個內置運算符|組成。你能夠用它來表達兩個表達式中任意一個爲true,那麼整個表達式都是true

和上面的邏輯與運算符同樣,邏輯運算符或也有一個短路的計算。當左邊的表達式的值爲true的時候,運算符右邊的值就不被計算了,由於不論它是true或者false都不會影響真個表達式的值。

在下面的例子中,第一個布爾值(hasDoorKey)是false,可是第二個值knowsOverridePasswordtrue。由於其中一個值爲true,那麼整個表達時的值就是true,通道是被容許的。

let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
//打印結果是Welcome!

混合邏輯運算

你能夠把多個邏輯運算符放到一塊兒,建立一個混合邏輯表達式。

if enterDoorCode && passedRetainScan || hasDoorKey || passedRetainScan {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
//打印結果是Welcome!

上面的這個例子中使用了多個邏輯運算符&& ||建立了一個混合邏輯運算符。然而,表達式&& ||都只能操做兩個值,因此這其實是三個簡單的邏輯表達式連續執行的結果,這個例子能夠被解讀爲:

若是咱們輸入了正確的密碼而且經過了視網膜的掃描,或者咱們有一把有效的鑰匙,或者咱們知道怎麼在緊急狀況下重置密碼,那麼就被容許進入。

enterDoorCodepassedRetainScan 以及hasDoorKey 由於 enterDoorCode 和 passedRetainScan的值都是false,固邏輯運算符& 值爲false 邏輯運算符|| hasDoorKey也爲false。可是緊急狀況重置密碼的權限是true。因此整個混合表達式的值就是true

注意:
swift的邏輯運算符&&||都是左結合式,它意味着混合表達式是由多個邏輯表達式以及計算的。他們在計算的時候優先計算左邊的表達式。

顯式括號

爲了使表達式易讀懂,咱們有時候會在合適的地方用括號來包含一個邏輯,固然這個括號多是非必要的。在上個關於門權限的例子中,咱們把第一部分用括號括起來了,這樣看起來邏輯更加明確:

if (enterDoorCode && passedRetainScan) || hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
//打印結果是Welcome!

經過這個括號咱們能清楚的看到在整個邏輯表達式中前兩個值是邏輯表達式中獨立的一部分。雖然最終的輸出結果沒有變化,可是整個邏輯表達式顯得更容易讀懂。可讀性有時候比簡潔性更加劇要,爲了使你的代碼邏輯更加清晰在合適的地方加上括號吧。

更多swift4.1翻譯請查看github

相關文章
相關標籤/搜索