Operator methods - RaduG/swift_learning GitHub Wiki

Overview

Operators can be implemented on custom structs / classes.

Binary operators

struct Vector2D {
  let x: Double
  let y: Double
}

extension Vector2D {
  static func + (left: Vector2D, right: Vector2D) -> Vector2D {
    return Vector2D(x: left.x + right.x, y: left.y + right.y)
  }
}

let vector1 = Vector2D(x: 5, y: 7)
let vector2 = Vector2D(x: 1, y: 10)
print(vector1 + vector2)

Prefix operator

extension Vector2D {
  static prefix func -(vector: Vector2D) -> Vector2D {
    return Vector2D(x: -vector.x, y: -vector.y)
  }
}

let vector1 = Vector2D(x: 5, y: 7)
print(-vector1)

Postfix operator

extension Vector2D {
  static postfix func ++(vector: Vector2D) -> Vector2D {
    return Vector2D(x: vector.x + 1, y: vector.y + 1)
  }
}

let vector1 = Vector2D(x: 5, y: 7)
print(vector1++)

Compound assignment operator

extension Vector2D {
  static func + (left: Vector2D, right: Vector2D) -> Vector2D {
    return Vector2D(x: left.x + right.x, y: left.y + right.y)
  }
  
  static func +=(left: inout Vector2D, right: Vector2D) {
    left = left + right
  }
}

var vector1 = Vector2D(x: 5, y: 7)
let vector2 = Vector2D(x: 10, y: 10)
vector1 += vector2
print(vector1)

Equivalence operator

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

let vector1 = Vector2D(x: 5, y: 7)
let vector2 = Vector2D(x: 10, y: 10)
let vector3 = Vector2D(x: 10, y: 10)
print(vector1 == vector2)
print(vector2 == vector3)

If conforming to Equatable, swift will automatically provide an implementation for != as the negation of ==.

Custom operators

A custom operator must be declared and if it is an infix operator, its precedence must too.

infix operator **: MultiplicationPrecedence

struct Vector2D {
  let x: Double
  let y: Double
}

extension Vector2D: Equatable {
  static func **(left: Vector2D, right: Int) -> Vector2D {
    var x = left.x
    var y = left.y
    for _ in 1..<right {
      x = x * left.x
      y = y * left.y
    }

    return Vector2D(x: x, y: y)
  }
}

let vector1 = Vector2D(x: 5, y: 7)
print(vector1 ** 2)