Swift4.2 基本运算符

Swift 支持大多数标准 C 语言运算符,并改进了一些功能,很简单(´・(00)・`)

基本运算符

Swift 支持大多数标准 C 语言运算符,并改进了一些功能以消除常见的编码错误。为防止误用等号运算符 (==), 赋值运算符 (=)并不返回值。为了避免数值在计算时超出它们类型允许值的范围,出现意外结果,算术运算符 (+, -, *, /, % 等) 会检测且不允许值溢出。你可以使用 Swift 值溢出运算符来选择值溢出行为,相关描述请参见 溢出运算符

Swift 还提供了 C 语言中不存在的范围运算符,如 a..<ba...b ,作为表示区间值的快捷方式。

术语

运算符分为一元的、二元的和三元的:

  • 一元 运算符运算单个目标值(例如 -a )。
    一元 前缀 运算符显示在目标值之前(例如 !b),而一元 后缀 运算符显示在目标值之后(例如 c!)。
  • 二元 运算符运算两个目标值(例如 2 + 3)并且是 中缀的 因为它们显示在两个目标值之间。
  • 三元 运算三个目标值。像 C , Swift 只有一个三元运算符,就是三元条件运算符(a ? b : c)。

被运算符影响的值叫做 操作数 。在表达式 1 + 2 中, + 号是二元运算符, 12 是它的两个操作数。

赋值运算符

与 C 和 Objective-C 中的赋值运算符不同,Swift 的赋值运算符本身不返回值。下方的语句是无效的:

1
2
3
if x = y {
// 这是无效的,因为 x = y 不返回值
}

算术运算符

与 C 以及 Objective-C 不同的是, 在 Swift 中, 默认情况下算术运算符不允许值溢出。但是你能通过用 Swift 的溢出符号 (正如 a &+ b)去加入值溢出的行为。参考 Overflow Operators
加号同样支持String的连接:

1
"hello, " + "world"  // 等于 "hello, world"

取余运算符

注意
取余运算符 (%) 在别的一些语言中的意思是 模运算符 。不过,严格意义上在 Swift 中,对于负数来说它是取余运算而不是模运算。

一元减号运算符

1
2
3
let three = 3
let minusThree = -three // minusThree 等于 -3
let plusThree = -minusThree // plusThree 等于 3, or "--3"

一元加号运算符

1
let c = a + b

复合赋值运算符

和 C 类似:

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

注意
复合赋值运算符没有返回值。例如,你不能这么写 let b = a += 2

比较运算符

Swift 支持所有的标准 C 系比较运算符

注意
Swift 还提供了两个恒等运算符(===!==),你可以用它们来判断两个对象引用是否指向同一个实例。

如果两个元组有着相同数量和类型的元素,你就可以比较它们。元组的比较是从左向右,逐个比较的,直到遇到不相等的元素为止。也就是说,每次元素比较的返回值都决定着整个元组比较的结果。如果所有对应元素都相等,那么这两个元组就是相等的。比如:

1
2
3
(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"。

如果一个操作符可以被用来比较两个元组的每个对应元素,那么它就可以被用来比较这两个元组。比如像以下代码演示的那样,你可以比较两个类型为 (String, Int) 的元组,因为 StringInt 类型的值都可以用 < 操作符比较。与之形成对比的是,两个 (String, Bool) 类型的元组不能用 < 比较,因为 < 运算符在 Bool 上没有定义。

1
2
("blue", -1) < ("purple", 1)        // 正确,比较的结果为 true
("blue", false) < ("purple", true) // 错误,因为两个布尔类型的值不能用 < 比较。

注意
Swift 标准库只定义了用于比较拥有七个以内元素的元组的操作符,如果想要比较两个拥有七个或更多元素的元组,你就需要自己来实现该运算符。

三元运算符

它的形式是 question ? answer1 : answer2

空合运算符

空合运算符 (a ?? b) 在可选型 a 有值的时候就为它解包,在 anil 的时候就返回默认值 b 。表达式 a 一定要是可选型。表达式 ba 存储的值类型一定要一致。

空合运算符是下面代码的简写:

1
a != nil ? a! : b

注意
如果 a 的值不是 nil ,那么 b 的值将不会被计算。这就是 短路求值。

区间运算符

Swift 包含的一些 区间运算符,其实是数值区间表达式的缩写。

闭合区间运算符

闭合区间运算符 (a...b) 表示从 ab 的区间,并且包含 aba 一定不能大于 b

当你想遍历一个区间中的值加以利用时,那么闭合区间运算符就在合适不过了,比如在用 for-in 循环的时候:

1
2
3
4
5
6
7
8
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

半开区间运算符

半开区间运算符(a..<b)定义了一个从 ab 但不包括 b 的区间。之所以称之为半开,是因为该区间只包含第一个值,而不包含最后一个值。与闭区间运算符一样,a 绝不可以大于 b。如果 a 等于 b 的话,就表示该区间为空。

当你作用于一个索引从 0 开始的列表(比如数组)时,如果你想要从 0 开始,一直数到(但不过包括)列表的长度,半开区间就显得非常有用了:

1
2
3
4
5
6
7
8
9
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

单侧区间

闭区间运算符还有另外一种形式,表示向一个方向尽可能地延伸——例如在数组中,一个包含了从索引为 2 开始一直到结尾的所有元素的区间。在这些情况下,你可以省去该区间操作符一侧的值。因为这种区间只有一侧有值,所以它们叫作 单侧区间,例如:

1
2
3
4
5
6
7
8
9
10
11
12
for name in names[2...] {
print(name)
}
// Brian
// Jack

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

半开区间操作符如果只保留其终值就是它的单侧形式了。就像它的完全形式一样,终值本身并不是该区间的一部分,例如:

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

单侧区间不仅仅能被用于下标,还能用于一些其它情况。你无法遍历省略了初始值的单侧区间,因为那种形式没有明确指出遍历应该从哪儿开始。不过你可以遍历没有终值的单侧区间;需要注意的是,因为区间的延伸特性,请务必确保你的遍历循环里有一个清晰的用于结束循环的条件。你还可以检查一个单侧区间是否包含某个特定的值,就像下边代码展示的那样。

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

逻辑运算符

Swift 支持基于 C 语言中的 3 种标准逻辑运算符

  • 逻辑非(!a
  • 逻辑与(a && b
  • 逻辑或(a || b

混合逻辑运算

你可以组合多个逻辑运算符来创建更长的复合表达式:

1
2
3
4
5
6
if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
print("Welcome!")
} else {
print("ACCESS DENIED")
}
// 打印 "Welcome!"

注意
Swift 逻辑运算符 &&|| 都是左关联的,这意味着具有多个逻辑运算符的复合表达式首先判断最左边的子表达式。

显性括号

括号清楚地表明了前两个值被视为整体逻辑中独立可能状态的一部分。这个复合表达式的结果并没有改变,但是其整体的意图对于读者来说更加清晰了。易读性总是优先于简洁性;在可以帮助你明确意图的地方,使用括号吧。