赋值运算符
=
将值绑定给变量或常量,如果右侧是元组则会将其拆成多个变量或常量。
let a = 5
var b = 10
let (x, y) = (1, 2)
算术运算符
默认提供五种算术运算符和它们的组合形式:
- 加法:
+
、+=
- 减法:
-
、-=
- 乘法:
*
、*=
- 除法:
/
、/=
- 取余:
%
比较运算符
比较运算符会返回一个Bool
类型的值表示条件是否成立:
- 等于:
==
- 不等于:
!=
- 大于:
>
- 小于:
<
- 大于等于:
>=
- 小于等于:
<=
还有===
和!==
用于判断两个对象的引用是否相同。
如果两个元组有相同数量(小于 7 个)的元素,且每个元素都是可比较的(如Int
、String
,不包括Bool
),则可以使用比较运算符来比较这两个元组。
三元条件运算符
如果给定条件question
成立,就返回answer1
,否则返回answer2
。
question ? answer1 : answer2
合并空值运算符
如果可选项a
有值就使用a
,如果是nil
就使用b
的值。
a ?? b
区间运算符
闭区间运算符a...b
定义从a
到b
的集合,并且a
的值不能大于b
的值。
半开区间运算符a..<b
定义了从a
到b - 1
的集合,并且a
的值不能大于b
的值。
如果省略了a
或b
,那么它们默认是无穷远。所以省略a
时不能用for
遍历,因为编译器不知道要从哪里开始,省略b
时需要有终止条件,否则程序一直运行直到崩溃。
逻辑运算符
逻辑运算符可以修改或合并布尔值true
和false
:
- 逻辑非:
!
- 逻辑与:
&&
- 逻辑或:
||
&&
和||
都具有短路特性,如果左侧的表达式已经可以得到结果,就不会计算右侧的表达式。
位运算符
位取反运算符~
:对所有比特位进行取反操作,即1
变0
,0
变1
。
位与运算符&
:对两个数的比特位进行合并,当两个比特位都是1
时才得到1
。
位或运算符|
:对两个数的比特位进行合并,当两个比特位都不是0
时就返回1
。
位异或运算符^
:对两个数的比特位进行合并,当两个比特位不相等时返回1
。
位左移运算符<<
将所有比特位向左移动n
位,左侧溢出的部分被丢弃,右侧空出的部分补0
。
位右移运算符>>
将所有比特位向右移动n
位,右侧溢出的部分被丢弃,左侧空出的部分补0
。
如果对有符号整数使用<<
或>>
,符号位不参加运算,即得到的结果与原来的数符号保持一致。
溢出运算符
为整数赋一个超出它容量的值时,Swift 会报错,但使用&+
、&-
和&*
代替算术运算符时可以让系统支持整数溢出运算,溢出的部分会被截断。
运算符重载
要对类和结构体使用上面介绍的运算符,则需要对运算符进行重载。
下面这个例子定义了一个用来表示二维坐标向量的结构体,并定义了func +
来重载+
运算符:
struct Vector2D {
var x = 0.0, y = 0.0
}
extension Vector2D {
static func + (left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y + right.y)
}
}
let vecA = Vector2D(x: 3.0, y: 1.0)
let vecB = Vector2D(x: 2.0, y: 4.0)
let vecC = vecA + vecB // (5.0, 5.0)
如果需要重载的是一元运算符,则在func
关键字前面需要加prefix
或postfix
限定符:
extension Vector2D {
static prefix func - (vec: Vector2D) -> Vector2D {
return Vector2D(x: -vec.x, y: -vec.y)
}
}
let vecD = -vecA // (-3.0, -1.0)
如果重载的是组合算术运算符,由于左侧的值会被修改,需要设置成inout
类型:
extension Vector2D {
static func += (left: inout Vector2D, right: Vector2D) {
left = left + right
}
}
let vecD += vecB // (-1.0, 3.0)
如果重载的是==
或!=
,则需要使用标准库的Equatable
协议:
extension Vector2D: Equatable {
static func == (left: Vector2D, right: Vector2D) -> Bool {
return (left.x == right.x) && (left.y == right.y)
}
}
自定义运算符
使用operator
关键字声明新的运算符,还要指定prefix
(一元前缀)、infix
(二元中缀)或postfix
(一元后缀)限定符。
extension Vector2D {
static prefix func +++ (vector: inout Vector2D) -> Vector2D {
vector += vector
return vector
}
}
let vecA = Vector2D(x: 1.0, y: 4.0)
let vecB = +++vecA // (2.0, 8.0)