前言

  • Swift 语言支持大部分标准 C 语言的运算符,并且改进了许多特性来使我们的代码更加规范,其中主要包含算数运算符、区间运算符、逻辑运算符、关系运算符、赋值运算符、自增自减运算符、溢出运算符等。

1、赋值运算符

  • Swift 使用符号 = 来表示赋值运算,如果赋值的对象是一个元组,那么元组内成员的值在赋值操作中是一一对应的。

= 赋值

  • Swift 赋值语句是没有返回值的,如果你使用如下语句系统会直接提示错误,避免开发人员犯将 == 误写成 = 的设计性错误。
if x = y {}

2、算数运算符

  • Swift 支持基本的加减乘除和求余运算。

+
-
*
/
% 求余

  • Swift 中的加法运算 + 除了可以用来对整数和浮点数做加法,还可以直接拼接字符串。
  • Swift 中的求余运算 % 可以对浮点数进行求余。
  • 求余运算中当参与运算的两个操作数符号不一致时,求余运算符结果的符号会和第一个操作数一致。
"bei jing" + " huan ying ni"    // "bei jing huan ying ni"
5.1 % 2                           // 1.1
-5 % 2                            // -1

3、自增自减运算符

  • Swift 3.0 之前支持 ++-- 自增自减运算符,从 3.0 版本被废弃。3.0 之后使用自增自减运算可以使用下面的写法。

+= 自增
-= 自减

  • 相比于 ++--,上面的写法还可以指定自增和自减的 “步长”。
var a = 1

a += 1  // 自增,2
a -= 1  // 自减,0

4、组合赋值运算符

  • Swift 提供把其它运算符和赋值运算符组合在一起执行的运算。

+= 加等于
-+ 减等于
*= 乘等于
/= 除等于
%= 余等于

  • 要实现一个组合赋值符号需要把运算符的左参数设置成 inout 类型,从而使运算符函数体内部可以直接修改他的值。
func += (inout lhs: Int, rhs: Int) {
    lhs = lhs + rhs
}

5、关系运算符

  • 所有标准 C 中的比较运算符在 Swift 中都可以使用,比较运算会返回 Bool 类型的比较结果。

== 等于
!= 不等于
> 大于
>= 大于等于
< 小于
<= 小于等于
=== 恒等于
!== 不恒等于

  • 恒等于运算符 === 用于判断两个对象是否引用同一个类实例,在 Swift 中可以用在任何类型的比较中。
  • 原生的关系运算符 ==!= 不能判断自定义的类型是否相等,需要重载。
1 == 3      // false
1 != 3      // true
1 === 3     // false
1 !== 3     // true

6、条件运算符

  • 条件运算符是 if-else 结构的一种简化,它可以通过一个 Bool 类型判断条件的真假来选择执行哪个操作。

判断条件 ? 表达式1 : 表达式2

  • 如果判断条件表达式的值为真,则返回表达式 1 的值,否则返回表达式 2 的值。
var height = 180
var name = height > 160 ? "xiaoming" : "xiaogang"    // "xiaoming"

7、逻辑运算符

  • Swift 沿用了 C 语言中的三种逻辑运算符 与、或、非,逻辑运算符的操作对象是布尔值。

&&
||
!

  • 逻辑与 && 运算,如果第一个值为 false,表达式将直接返回 false,而不会去计算第二个操作数,这种机制被称为 “短路计算”。
  • 逻辑或 || 运算,如果第一个值为 true,表达式将直接返回 true,而不会去计算第二个操作数。
  • 逻辑非 ! 运算,运算符与操作数之间不能有空格。

8、位运算符

  • Swift 中可以使用所有和 C 语言一样的位运算符。

& 按位与
| 按位或
~ 按位取反
^ 按位异或
<< 按位左移
>> 按位右移

  • 按位左移相当于把这个数乘以 2 的因子。
  • 按位右移相当于把这个数除以 2 的因子。
  • 对于无符号数按位右移时,被移出整型存储边界的低位将被直接抛弃,而右移留下的高位空白位用 0 来填充,这种机制称为 “逻辑移位”。
  • 对于有符号数按位右移时,高位不足时会使用符号位(正数位 0,负数为 1)填充空白位,这种机制被称为 “算数移位”。

9、溢出运算符

  • Swift 为整型计算提供了 5 个 & 符号开头的溢出运算符。

&+ 溢出加法
&- 溢出减法
&* 溢出乘法
&/ 溢出除法
&% 溢出求余

  • Swift 语言中的数值运算默认是不可以值溢出的,但是在某些特定的场合一定需要使用值溢出时,可以使用溢出运算来达到有目的的溢出。
var intMaxNum = Int8.max &+ 1      // -128 值溢出被截断
var intMinNum = Int8.min &- 1      // 127  值溢出被截断

10、单目正负号运算符

  • 我们通常使用单目负号 - 来切换数值类型的正负。

- 负号
+ 正号

  • 单目正负号运算符通常用于切换值类型的正负,单目正负运算符与操作数之间不能有空格。
var i = 2
var b = -i      // -2

11、连接运算符

  • 两个字符串可以连接在一起成为一个新字符串,这种操作被称为字符串连接,在 Swift 中连接字符串可以使用 + 符号。

+ 连接

12、区间运算符

  • 在 OC 中,我们可以使用 Range 函数来指示一个起始位置和长度,从而恒定一个范围。Swift 中的范围使用起来要方便的多。

a...b 闭区间
a..<b 半闭区间

  • 闭区间 a...b 定义一个包含从 a 到 b(包括 a 和 b)范围内所有值的空间。
  • 半闭区间 a..<b 定义一个包含从 a 到 b(包括 a,不包括 b)范围内所有值的空间。

13、自定义运算符

  • 自定义运算符是新的编程语言才支持的特性,不同于组合赋值运算符,你可以使用 / = - + * % < > ! & | ^ ~ 来组合构成新的运算符。
  • 自定义一个运算符通常需要先声明再实现其功能,声明自定义的运算符需要使用 operator 关键字。
operator      :表示要进行运算符重载。

infix         :表示这是一个二元运算符,操作符在两个操作数中间。 
prefix        :表示这是一个一元运算符,操作符在操作数前边。
postfix       :表示这是一个一元运算符,操作符在操作数后边。

associativity :结合性,包含 left(左结合)、right(右结合)和 none(自动),默认值为 none。

precedence    :优先级,默认为 100,可省略。
  • 自定义运算符 <>
// 声明自定义运算符 <>
infix operator <> {associativity none precedence 100}

// 实现自定义的运算符 <>
func <> (lhs: Int, rhs: Int) -> Int {

    return (lhs + rhs) * (lhs - rhs)
}

// 输出值等于 20
let n1 = 6   
let n2 = 4
let value = n1 <> n2 
print(value)

14、运算符重载

  • 让已有的运算符对自定义的类和结构进行运算或者重新定义已有运算符的运算规则,这种机制被称为 “运算符重载”。
  • 运算符重载可以使同一个运算符在处理不同数据类型时,实现的是不同的功能。
  • 默认的赋值符 = 和三目条件运算符 ? : 是不可重载的。
  • Swift 语言和其他高级语言不同,其原生的关系运算符不能判断自定义的类型是否相等,所以我们需要重载自定义的类和结构的比较符 ==!=
func == (left: CenterPointer, right: CenterPointer) -> Bool {
    return (left.x == right.x) && (left.y == right.y)
}

func != (left: CenterPointer, right: CenterPointer) -> Bool {
    return  !(left == right)
}

15、运算符优先级和结合性

  • 运算符的优先级使得一些运算符优先于其他运算符,从而使得高优先级的运算符会先被计算。
  • 运算符的结合性用于定义相同优先级的运算符在一起时和表达式结合或关联的规则。
  • 结合性(associativity)包含 left(左结合)、right(右结合)和 none(自动),结合性的默认值为 none。优先级( precedence )默认为 100。
// 指定运算符的优先级和结合性 左结合 优先级 140
infix operator +- {associativity left precedence 140}
  • 运算符优先级和结合性
运算符  |      名称        |    结合性    |   优先级
---------|-----------------|-------------|-------------
   <<    |    按位左移       |    无       |    160
   >>    |    按位右移       |    无       |    160
   *     |    乘            |    左       |    150
   /     |    除            |    左       |    150
   %     |    求余           |    左      |     150
   &*    |    忽略溢出乘      |    左      |     150
   &/    |    忽略溢出除      |    左      |     150
   &%    |    忽略溢出求余    |    左       |    150
   &     |    按位与         |    左       |    150
   +     |    加            |    左       |    140
   -     |    减            |    左       |    140
   &+    |    溢出加         |    左       |    140
   &-    |    溢出减         |    左       |    140
   |     |    按位或         |    左       |    140
   ^     |    按位异或        |    左      |    140
   ..    |    半闭区间        |    无      |    135
   ...   |    全闭区间        |    无      |    135
   is    |    类型检查        |    无      |    132
   as    |    类型转换        |    无      |    132
   <     |    小于           |    无      |    130 
   <=    |    小于等于        |    无      |    130
   >     |    大于           |    无      |    130
   >=    |    大于等于        |    无      |    130
   ==    |    等于           |    无      |    130
   !=    |    不等于          |    无      |    130
   ===   |    恒等于          |    无      |    130
   !==   |    不恒等于        |    无      |    130
   ~=    |    模式匹配        |    无      |    130
   &&    |    逻辑与          |    左      |    120
   ||    |    逻辑或          |    左      |    110
   ? :   |    条件            |    右      |    100
   =     |    赋值            |    右      |    90  
   *=    |    复合乘赋值       |    右      |    90
   /=    |    复合除赋值       |    右      |    90
   %=    |    复合求余赋值     |    右      |    90
   +=    |    复合加赋值       |    右      |    90
   -=    |    复合减赋值       |    右      |    90
   <<=   |    复合按位左移赋值  |    右      |    90
   >>=   |    复合按位右移赋值  |    右      |    90
   &=    |    复合按位与赋值    |    右      |    90
   ^=    |    复合按位异或赋值  |    右      |    90
   |=    |    复合按位或赋值    |    右      |    90
   &&=   |    复合逻辑与赋值    |    右      |    90
   ||=   |    复合逻辑或赋值    |    右      |    90