跳转至

运算符重载

运算符重载

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

运算符重载 必须是static

struct Vector {
    let x: Int
    let y: Int
}

extension Vector {
    //已有的运算符
    static func + (fistVector: Vector, secondVector: Vector) -> Vector {
        return Vector(x: fistVector.x + secondVector.x, y: fistVector.y + secondVector.y)
    }

    static func - (fistVector: Vector, secondVector: Vector) -> Vector {
        return fistVector + -secondVector//这里会用到下面的一元运算符重载
    }
}

func test() {
    let x = Vector(x: 10, y: 20)
    let y = Vector(x: 20, y: 30)
    let z = x + y
    print(z)
}

一元运算符重载

要实现前缀或者后缀运算符,需要在声明运算符函数的时候在 func 关键字之前指定 prefix 或者 postfix 限定符

struct Vector {
    let x: Int
    let y: Int
}

extension Vector {
    //一元运算符重载
      //要实现前缀或者后缀运算符,需要在声明运算符函数的时候在 func 关键字之前指定 prefix 或者 postfix 限定符
    //前缀 -
    static prefix func - (vector: Vector) -> Vector {
        return Vector(x: -vector.x, y: -vector.y)
    }
}

func test() {
    let x = Vector(x: 10, y: 20)
    print(-x)
}

组合赋值运算符重载

组合赋值运算符将赋值运算符( = )与其它运算符进行结合。

在实现的时候,需要把运算符的左参数设置成 inout 类型,因为这个参数的值会在运算符函数内直接被修改

struct Vector {
    let x: Int
    let y: Int
}

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

func test() {
    var x = Vector(x: 10, y: 20)
    let y = Vector(x: 20, y: 30)
    x += y
    print(x)
}

等价运算符重载

自定义类和结构体不接收等价运算符的默认实现,也就是所谓的“等于”运算符( == )和“不等于”运算符( != )。

要使用等价运算符来检查你自己类型的等价,需要和其他中缀运算符一样提供一个“等于”运算符,并且遵循标准库的 Equatable 协议

struct Vector {
    let x: Int
    let y: Int
}

extension Vector: Equatable {
    static func == (left: Vector, right: Vector) -> Bool {
        return (left.x == right.x) && (left.y == right.y)
    }
}

func test() {
    var x = Vector(x: 10, y: 20)
    let y = Vector(x: 20, y: 30)
    print(x == y)
}

Swift 为以下自定义类型提供等价运算符合成实现:

  • 只拥有遵循 Equatable 协议存储属性的结构体
  • 只拥有遵循 Equatable 协议关联类型的枚举
  • 没有关联类型的枚举
struct Vector3D: Equatable {
    var x = 0.0, y = 0.0, z = 0.0
}

func test() {
    let v1 = Vector3D(x: 2.0, y: 3.0, z: 4.0)
    let v2 = Vector3D(x: 2.0, y: 3.0, z: 4.0)
    if v1 == v2 {
        print("是相等的")
    }
}

自定义运算符

除了实现标准运算符,在 Swift 当中还可以声明和实现自定义运算符(custom operators)。

新的运算符要在全局作用域内,使用 operator 关键字进行声明,同时还要指定 prefix 、infix 或者 postfix 限定符

  • infix中缀运算符
  • prefix前缀运算符
  • postfix后缀运算符

自定义一元运算符

struct Vector {
    let x: Int
    let y: Int
}

// MARK: 自定义一元运算符
prefix operator +++
extension Vector {
    static prefix func +++ (vector: inout Vector) -> Vector {
        vector += vector//上面重写了
        return vector
    }
}

自定义中缀运算符的优先级和结合性

自定义的中缀( infix )运算符也可以指定优先级和结合性

每一个自定义的中缀运算符都属于一个优先级组

优先级组指定了自定义中缀运算符和其他中缀运算符的关系

struct Vector {
    let x: Int
    let y: Int
}

// MARK: 自定义中缀运算符
infix operator +- : AdditionPrecedence//AdditionPrecedence加法的优先级组
//infix operator +- : MultiplicationPrecedence//MultiplicationPrecedence乘法的优先级组
extension Vector {
    static func +- (left: Vector, right: Vector) -> Vector {
        return Vector(x: left.x + right.x, y: left.y - right.y)
    }
}

// MARK: 自定义运算符优先级组
infix operator *^ : HHPrecedence
//自定义运算符优先级组
precedencegroup HHPrecedence {
    //    higherThan: lower group names
    lowerThan: AdditionPrecedence
    associativity: left
    //    assignment: assignment
}
extension Vector {
    static func *^ (fistVector: Vector, secondVector: Vector) -> Vector {
        return Vector(x: fistVector.x * secondVector.x, y: fistVector.y * secondVector.y)
    }
}

func testq() {
    let x = Vector(x: 10, y: 20)
    let y = Vector(x: 20, y: 30)
    let z = Vector(x: 50, y: 40)
    let s = x +- y *^ z
    print(s.x)
    print(s.y)
}

运算符重载 实现多线程依赖

precedencegroup OperationDependency{
    associativity: left
}
infix operator ==> : OperationDependency
extension Operation{
    static func ==>(lhs: Operation, rhs: Operation) -> Operation{
        rhs.addDependency(lhs)
        return rhs
    }
}

func test() {
    let opt1 = BlockOperation.init{
        for _ in 0..<3{
            print("A Excute:\(Thread.current)")
        }
    }
    let opt2 = BlockOperation.init{
        for _ in 0..<3{
            print("B Excute:\(Thread.current)")
        }
    }
    let opt3 = BlockOperation.init{
        for _ in 0..<3{
            print("C Excute:\(Thread.current)")
        }
    }

    //依赖
    opt1 ==> opt2 ==> opt3
}