高级运算符

位运算符

Swift支持C语言中全部位运算符

按位取反运算符 ~

let initialBits: UInt8 = 0b00001111
let invertedBits = ~initialBits // 等于 0b11110000

按位与运算符 &

按位或运算符 |

两个数的对应位中有任意一个为1时,返回的对应位就为1

按位异或运算符 ^

当两个数对应位不相同时,返回1

按位移位运算符

左移<< 右移>>

无符号整数的移位运算是:
逻辑移位:对于移除整型存储范围的位都会被舍弃

let pink: UInt32 = 0xCC6699
let redComponent = (pink & 0xFF0000) >> 16 // redComponent 是 0xCC,即 204
let greenComponent = (pink & 0x00FF00) >> 8 // greenComponent 是 0x66, 即 102
let blueComponent = pink & 0x0000FF // blueComponent 是 0x99,即 153

有符号整数的移位运算:
算术移位:当对整数进行按位右移时,对于移位产生的空白位使用符号位进行填充(逻辑移位中为0填充),左移规则与逻辑移位相同

溢出运算符

Swift中的运算符默认不会溢出,溢出会被捕获并且报告为错误。

var potentialOverflow = Int16.max
// potentialOverflow 的值是 32767,这是 Int16 能容纳的最大整数
potentialOverflow += 1
// 这里会报错

我们可以选在数值溢出时采用阶段处理,而不报错:采用已出运算符(以&开头)

&+ &- &*

对于无符号与有符号整型数值来说,当出现上溢时,它们会从数值所能容纳的最大数变成最小的数。同样地,当发生下溢时,它们会从所能容纳的最小数变成最大的数。

优先级和结合性

注意:
Swift中的优先级与C语言中完全不一致

运算符函数

类和结构体可以为现有的运算符提供自定义实现-->运算符重载

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)
    }
}

对于结构体Vector2.0,运算符函数被定义为类方法,名字与要重载的+一致

因为加法运算并不是一个向量必须的功能,因此这个类被定义在扩展而不是原结构体声明中

这个函数被定义为全局的,因此任意Vector2D示例都可以使用这个运算符:

let vector = Vector2D(x: 3.0, y: 1.0)
let anotherVector = Vector2D(x: 2.0, y: 4.0)
let combinedVector = vector + anotherVector
// combinedVector 是一个新的 Vector2D 实例,值为 (5.0, 5.0)

前缀和后缀运算符

不仅加法似的中缀运算符,类和结构体也可以提供单目运算符实现

extension Vector2D {
//prefix表明是前缀运算符的实现
    static prefix func - (vector: Vector2D) -> Vector2D {
        return Vector2D(x: -vector.x, y: -vector.y)
    }
}

let positive = Vector2D(x: 3.0, y: 4.0)
let negative = -positive
// negative 是一个值为 (-3.0, -4.0) 的 Vector2D 实例
let alsoPositive = -negative
// alsoPositive 是一个值为 (3.0, 4.0) 的 Vector2D 实例

实现单目运算符需要用prefix或者postfix来指明前缀后后缀

复合赋值运算符

对于复合赋值运算符例如:+= -=
需要在实现时将做参数设置为inout类型,这样参数值可以在函数中被修改

extension Vector2D {
    static func += (left: inout Vector2D, right: Vector2D) {
        left = left + right
    }
}

不能对默认的赋值运算符=进行重载。只能重载组合赋值运算符,也无法对三目运算符进行重载

等价运算符

通过对自定义类或结构体进行==!=运算符实现来判断其是否“相等”

//实现方法与中缀运算符相同
extension Vector2D {
    static func == (left: Vector2D, right: Vector2D) -> Bool {
        return (left.x == right.x) && (left.y == right.y)
    }
    static func != (left: Vector2D, right: Vector2D) -> Bool {
        return !(left == right)
    }
}

自定义运算符

除了实现标准运算符外还可以声明和实现自定义的运算符

新的运算符要使用operator关键字在全局作用域内进行定义,同时还要指定prefixinfix或者postfix修饰符:

prefix operator +++ {}
//定义了+++的前缀运算符  全局作用域
//这个运算符现在没有任何意义

我们针对Vector2D结构体来实现+++运算符

extension Vector2D {
    static prefix func +++ (vector: inout Vector2D) -> Vector2D {
        vector += vector
        return vector
    }
}
//我们将+++实现为前面重载的运算符+=自身的值

自定义中缀运算符优先级

每个自定义中缀运算符都属于某个优先级组。这个优先级组指定了这个运算符和其他中缀运算符的优先级和结合性

//自定义中缀运算符+- 属于AdditionPrecedence优先组
infix operator +-: AdditionPrecedence

extension Vector2D {
    static func +- (left: Vector2D, right: Vector2D) -> Vector2D {
        return Vector2D(x: left.x + right.x, y: left.y - right.y)
    }
}
let firstVector = Vector2D(x: 1.0, y: 2.0)
let secondVector = Vector2D(x: 3.0, y: 4.0)
let plusMinusVector = firstVector +- secondVector
// plusMinusVector 是一个 Vector2D 实例,并且它的值为 (4.0, -2.0)

AdditionPrecedence优先组为+-等默认的优先级组