Swift基本运算符

Posted by Buddy on June 2, 2024

基本运算符

赋值运算符

赋值运算符(a = b)用于将 b 的值初始化或更新到 a 中:

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

如果赋值运算符右侧是一个包含多个值的元组,则其元素可以一次性分解为多个常量或变量:

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

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

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

这种特性防止了在实际需要使用等于运算符(==)时误用赋值运算符(=)。通过使 if x = y 无效,Swift 帮助您避免此类错误。

算术运算符

Swift 支持所有数字类型的四种标准算术运算符:

  • 加法 (+)
  • 减法 (-)
  • 乘法 (*)
  • 除法 (/)

与 C 和 Objective-C 中的算术运算符不同,Swift 的算术运算符默认不允许值溢出。您可以通过使用 Swift 的溢出运算符(例如 a &+ b)选择允许值溢出行为。详见 溢出运算符

加法运算符也支持字符串连接:

"hello, " + "world"  // 结果是 "hello, world"

余数运算符(a % b)计算 b 的多少倍能装入 a 并返回剩余的值(称为余数)。

注意:

余数运算符 (%) 在其他语言中也被称为取模运算符。然而,Swift 中对于负数的行为意味着它实际上是一个余数而不是取模操作。

9 % 4    // 结果是 1
-9 % 4   // 结果是 -1

组合赋值运算符

像 C 一样,Swift 提供了组合赋值运算符,将赋值(=)与另一个操作结合。一个例子是加法赋值运算符(+=):

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

注意:

组合赋值运算符不返回值。例如,您不能编写 let b = a += 2

比较运算符

Swift 支持以下比较运算符:

  • 等于(a == b)
  • 不等于(a != b)
  • 大于(a > b)
  • 小于(a < b)
  • 大于或等于(a >= b)
  • 小于或等于(a <= b)
1 == 1   // 因为 1 等于 1,所以结果为 true
2 != 1   // 因为 2 不等于 1,所以结果为 true
2 > 1    // 因为 2 大于 1,所以结果为 true
1 < 2    // 因为 1 小于 2,所以结果为 true
1 >= 1   // 因为 1 大于或等于 1,所以结果为 true
2 <= 1   // 因为 2 不小于或等于 1,所以结果为 false

字符串和元组也可以进行比较,前提是每个元素之间的比较也是有效的。例如,两个类型为 (String, Int) 的元组可以使用 < 运算符进行比较,因为 String 和 Int 值都可以用 < 运算符进行比较。相反,两个类型为 (String, Bool) 的元组不能用 < 运算符进行比较,因为 < 运算符不能应用于 Bool 值。

(1, "zebra") < (2, "apple")   // 因为 1 小于 2,所以结果为 true;"zebra" 和 "apple" 不进行比较
(3, "apple") < (3, "bird")    // 因为 3 等于 3,且 "apple" 小于 "bird",所以结果为 true
(4, "dog") == (4, "dog")      // 因为 4 等于 4,且 "dog" 等于 "dog",所以结果为 true

Swift 标准库包括了适用于少于七个元素的元组的比较运算符。要比较包含七个或更多元素的元组,您必须自己实现比较运算符。

三元条件运算符

三元条件运算符是一个具有三个部分的特殊运算符,形式为 question ? answer1 : answer2。它是根据 question 是 true 还是 false 来判断并返回 answer1answer2 的一个快捷方式。

let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50 : 20)
// rowHeight 现在是 90

三元条件运算符是以下代码的简写:

let rowHeight: Int
if hasHeader {
    rowHeight = contentHeight + 50
} else {
    rowHeight = contentHeight + 20
}

使用三元条件运算符可以让代码更简洁,但要谨慎使用,因为其简洁性可能导致代码难以阅读。避免将多个三元条件运算符组合成一个复合语句。

空合运算符

空合运算符(a ?? b)将对可选类型 a 进行空值判断。如果 a 包含一个值就解包,否则返回一个默认值 b。表达式 a 必须是可选类型,表达式 b 必须与 a 的储存类型相同。

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

a != nil ? a! : b

如下例所示,空合运算符用于默认值提供更为简洁的代码:

let defaultColorName = "red"
var userDefinedColorName: String?   // 默认值为 nil

var colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName 的值为 nil,因此 colorNameToUse 被设置为默认值 "red"

如果 userDefinedColorName 值不为 nil,例如 “green”,则 colorNameToUse 将使用 “green”:

userDefinedColorName = "green"
colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName 不为 nil,因此 colorNameToUse 被设置为 "green"

范围运算符

Swift 提供了两种方便表达一个范围内数值的范围运算符。

闭区间运算符

闭区间运算符(a…b)定义了从 a 到 b 的一组值,且包含 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
半开区间运算符

半开区间运算符(a..<b)定义了从 a 到 b 的一组值,但不包括 b。它被称为半开区间,因为它包含第一个值但不包含最后一个值。

半开区间运算符在处理从 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

尽管数组有四个元素(count 为 4),但 0..<count 仅表示从 0 到 3 的索引(共四个值),且不包括数组的最终值(4)。

单侧区间

半开区间还有一种表达方法,用于表达从一个值到数组或字符串的结束。

for name in names[2...] {
    print(name)
}
// 输出:
// Brian
// Jack

上面的代码从索引 2 到数组的结尾进行迭代。

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

上面的代码从数组的开始到索引 2 进行迭代。

单侧区间可以与闭区间运算符结合使用。以下代码定义了一个从索引 1 到数组的结尾的单侧区间:

let range = ...5

以上代码定义了一个从负无穷大到 5 的单侧区间。在实际使用中,这种单侧区间主要用于与数组或字符串的结尾相关的场景。

逻辑运算符

逻辑运算符修饰或组合布尔逻辑值。Swift 支持 C 语言中的所有标准逻辑运算符。

逻辑非运算符

逻辑非运算符(!a)对一个布尔值取反,使 true 变为 false,false 变为 true。

let allowedEntry = false
if !allowedEntry {
    print("ACCESS DENIED")
}
// 输出 "ACCESS DENIED"
逻辑与运算符

逻辑与运算符(a && b)仅在 a 和 b 都为 true 时才为 true。

let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// 输出 "ACCESS DENIED"
逻辑或运算符
逻辑或运算符(a   b)在 a 或 b 为 true 时为 true。
let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// 输出 "Welcome!"
逻辑运算符组合

可以将多个逻辑运算符组合在一起使用,以创建更复杂的条件语句:

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

在 Swift 中,逻辑与运算符和逻辑或运算符都是左结合的,这意味着多个逻辑运算符将从左到右求值。

使用括号提高可读性

为了避免复杂表达式中逻辑运算符的优先级混淆,可以使用括号提高表达式的可读性:

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

括号使表达式更为清晰,并且可以确保按照预期的顺序进行求值。