【Swift 3.1】02 - 基本运算符 (Basic Operators)

基本运算符 (Basic Operators)

自从苹果2014年发布Swift,到现在已经两年多了,而Swift也来到了3.1版本。去年利用工作之余,共花了两个多月的时间把官方的Swift编程指南看完。现在整理一下笔记,回顾一下以前的知识。有需要的同学可以去看官方文档>>


术语 (Terminology)

运算符有一元、二元和三元:

  • 一元运算符只操作一个操作数(例如-a)。一元运算符写在操作数的前面或者后面,例如!bc!,并且运算符和操作数不能有空格。
  • 二元运算符操作两个操作数(例如2 + 3)。
  • 三元运算符操作三个操作数。像C语言一样,Swift只有一个三元运算符,a ? b : c

赋值运算符 (Assignment Operator)

赋值运算符用来初始化变量的值,或者更新变量的值

let b = 10
var a = 5
a = b
// a现在等于10

如果赋值运算符右边是一个有多个元素的多元组,多元组的元素可以一次性分解成多个常量或者变量:

let (x, y) = (1, 2)
// x等于1,y等于2

不同于C和OC,Swift中的赋值运算符本身不返回任何值。下面这个语句是非法的:

if x = y {
    // 这是非法的,因为x=y不返回任何值
}

算术运算符 (Arithmetic Operators)

Swift支持下面这四个标准的算术运算符:

  • 加 (+)
  • 减 (-)
  • 乘 (*)
  • 除 (/)
1 + 2       // 等于 3
5 - 3       // 等于 2
2 * 3       // 等于 6
10.0 / 2.5  // 等于 4.0

另外,+可以用来拼接String字符串:

"hello, " + "world"  // 等于 "hello, world"
求余运算符 (Remainder Operator)
9 % 4    // 等于 1

为了得出a % b的结果,%这个求余运算符计算下面的等式,并返回remainder

a = (b * some multiplier(另外一个乘数)) + 余数

some multiplierab的最大公约数。

上面的计算方法同样适用于负数:

-9 % 4 // 等于 -1

-94代入那个公式:

-9 = (4 * -2) + -1

所以返回-1

其实b前面的符号可以忽略,也就意味着a % ba % -b的返回值是相等的。

一元减号运算符 (Unary Minus Operator)
let three = 3
let minusThree = -3         // minusThree等于-3
let plusThree = -minusThree // plusThree等于3
一元加号运算符 (Unary Plus Operator)
let minusSix = -6
let alsoMinusSix = +minusSix // alsoMinusSix等于6

一元加号运算符不会改变操作数的值。但是为了保持对称,在代码中负数使用一元加号运算符,正数也加上一元加号运算符。

复合赋值运算符 (Compound Assignment Operators)

var a = 1
a += 2
// a 等于 3

a += 2其实是a = a + 2的简写。

注意:复合赋值运算符不会返回任何值,例如:我们不能这样写:let b = a += 2

比较运算符 (Comparison Operators)

Swift支持全部C语言的标准运算符:

  • 等于 (a == b)
  • 不等于 (a != b)
  • 大于 (a > b)
  • 小于 (a < b)
  • 大于或等于 (a >= b)
  • 小于或等于 (a <= b)

注意:Swift还额外提供了恒等运算符 (identity operator) (===!==),用来判断两个对象是否引用同一个实例。

所有的比较运算符都会返回一个Bool值:

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
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")
}
// Prints "hello, world", because name is indeed equal to "world".

还可以用来比较多元组,只要多元组的元素个数相同,并且每个元素都是可比较的。例如,IntString都是可以比较的,也就意味着多元组(Int, String)也是可以比较的。相反,Bool是不能比较的,所以元素中含有布尔值的多元组是不能比较的。

多元组在比较的时候,是从左到右一个一个比较,直到发现两个参与比较的值不相等,那么这两个不相等的元素的比较结果就作为两个多元组的比较结果。如果每个元素都各自相等,那么这个多元组就相等:

(1, "zebra") < (2, "apple")   // true 因为 1 is less than 2; "zebra" 和 "apple" 不用在比较
(3, "apple") < (3, "bird")    // true 因为 3 等于 3, 并且 "apple" 小于 "bird"
(4, "dog") == (4, "dog")      // true 因为 4 等于 4, 并且 "dog" 等于 "dog"

在上面的例子中,按照从左到右一个个比较的规则,因为1小于2,所以(1, "zebra")小于(2, "apple"),因为已经发现了两个不相等的元素,后面的元素将不再比较,尽管zebra大于apple。然而,当发现两个元素相等时,将会继续往下比较。

注意:Swift标准库只支持小于7个元素的多元组进行比较。如果多元组的元素大于或等于7个,我们必须自己实现比较运算符。

三元运算符 (Ternary Conditional Operator)

三元运算符是有三部分的比较特别的运算符,格式:question ? answer1: answer2。是下面这个代码的简写:

if question {
    answer1
}
else {
    answer2
}

例如下面这个例子:

let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50 : 20)
// rowHeight 等于 90

我们要避免使用三元运算符把多个判断条件组合在一起,因为这会造成代码很难读懂。

空合并运算符 (Nil-Coalescing Opeartor)

使用空合并运算符(a ?? b)来解包一个可选类型变量,如果a有值,返回a!,如果为nil,返回默认值ba必须是一个可选类型,b的类型必须a包含的值类型相同。

空合并运算符其实是下面这个代码的简写:

a != nil ? a! : b

下面举个例子:

let defaultColor = "red"
var userDefinedColorName: String? // 默认是nil

var colorNameToUse = userDefinedColorName ?? defaultColor
// userDefinedColorName 为 nil,所以 colorNameToUse被设置为默认值 "red"

范围运算符 (Range Operators)

闭合范围运算符 (Closed Range Operator)

闭合范围运算符(a...b)定义了一个从ab的范围,并且包括aba的值不能大于b

当你想使用一个范围的每一个值时,使用闭合运算符非常有用。例如:

for index in 1...5 {
    print("\(index) 乘以 5 等于 \(index * 5)")
}
// 1 乘以 5 等于 5
// 2 乘以 5 等于 10
// 3 乘以 5 等于 15
// 4 乘以 5 等于 20
// 5 乘以 5 等于 25
半闭合运算符 (Half-Open Range Operator)

半闭合运算符(a..<b)定义了一个从ab的范围,但是不包括ba的值不能大于b。如果a等于b,那么这个范围就是空的。

在使用下标以0开始的的列表,例如数组,但是不包含数组的长度,使用半闭合运算符非常合适:

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

逻辑运算符 (Logical Operators)

Swift支持这三个标准的逻辑运算符:

  • 逻辑非 (!a)
  • 逻辑与 (a && b)
  • 逻辑或 (a || b)
逻辑非运算符 (Logical NOT Operator)

逻辑非让一个布尔值取反,true变为falsefalse变为true

let allowedEntry = false
if !allowedEntry {
    print("拒绝访问")
}
// Prints "拒绝访问"
逻辑与运算符 (Logical AND Operator)

逻辑与运算符(a && b)两边的逻辑语句都为true时,整个语句才是true。如果有其中一个为false,整个语句就为false。实际上,只要第一个语句是false,第二个语句就不会在计算了,因为第二个语句无论是true还是false都不可能把最终的结果改为true

let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "ACCESS DENIED"
逻辑或运算符 (Logical OR Operator)

逻辑或运算符两边的逻辑语句,只要有一个是true,那整个语句就是true。如果第一个语句是true,第二个就不会再计算。

let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "Welcome!"
组合逻辑运算符 (Combining Logical Operators)
if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "Welcome!"

在这个例子中,使用多个&&||运算符来创建一个更长的复合语句。但是&&||运算符还是仅仅操作两个逻辑语句。上面的代码可以这么读:如果我们输入了正确的门密码并且通过了视网膜扫描,或者有门钥匙,或者我们知道紧急覆盖密码,那么就允许进入。

明确的括号 (Explicit Parentheses)

在恰当的位置加上括号,增强代码的易读性:

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

第二部分完。下个部分:【Swift 3.1】03 - 字符串和字符 (Strings and Characters)


如果有错误的地方,欢迎指正!谢谢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,874评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,102评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,676评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,911评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,937评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,935评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,860评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,660评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,113评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,363评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,506评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,238评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,861评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,486评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,674评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,513评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,426评论 2 352

推荐阅读更多精彩内容