Swift 操作符 Operators

1,160 阅读3分钟

在一些编程语言中, ** 可以让右操作数作为左操作数的指数来进行幂运算,但是在 Swift 中却没有。下面我们来新增一个自定义的 ** 操作符。

通常 ^ 被用作上标,但是它已经被用来执行一个 按位异或 运算了。

自定义运算符

要把 ** 作为运算符添加到 Swift 中,首先要定义一个运算符:

infix operator ** : BitwiseShiftPrecedence
  • infix 指定了它是一个二元操作符,有左右两个操作数参数
  • operator 是一个保留字,其必须写在 prefix , infix  或者 postfix 之后
  • ** 是运算符本身
  • BitwiseShiftPrecedence:指定运算符的优先级(precedencegroup)为 位移优先级 
infix operator ** : BitwiseShiftPrecedence
func ** (left: Double, right: Double) -> Double {
    pow(left, right)
}

2 ** 3
// 8

precedencegroup 优先级

一个操作符需要属于某个特定的优先级。precedencegroup 定义了一个操作符的优先级。Swift 标准库中内置了几种常用的操作符的优先级,加法优先级 (AdditionPrecedence) 、乘法优先级 (MultiplicationPrecedence)和位移优先级(BitwiseShiftPrecedence),更多的优先级可以查看 Swift 文档

下面是三个运算符优先级的定义:

precedencegroup AdditionPrecedence {
  associativity: left
  higherThan: RangeFormationPrecedence
}
precedencegroup MultiplicationPrecedence {
  associativity: left
  higherThan: AdditionPrecedence
}
precedencegroup BitwiseShiftPrecedence {
  higherThan: MultiplicationPrecedence
}

可以看出操作符优先级的定义和类型声明有些相似。如果内置的优先级不满足我们的要求,我们还可以自定义运算符的优先级。

// 自定义操作符的运算优先级
precedencegroup CustomerPrecedence {
    // 结合律
    associativity: none
    // 优先级设置
    // 高于加法和减法(AdditionPrecedence)
    higherThan: AdditionPrecedence
    // 低于乘法和除法(MultiplicationPrecedence)
    lowerThan: MultiplicationPrecedence
}

associativity 定义了结合律,即当多个同类的操作符顺序出现的计算顺序。比如常见的加减法都是 left,就是说多个加减法同时出现时按照从左往右的顺序计算 (因为加法满足交换律,所以这个顺序无所谓,但是减法的话计算顺序就很重要了)。不允许连续出现的操作符,可以写成 none。

higherThan 和 lowerThan 用于指定自定义的优先级高于和低于另一个优先级。

**如果合适的话,当创建了一个自定义的运算符时,还要创建相应的赋值操作符,就像 +  和 += 一样。 **

infix operator **= : BitwiseShiftPrecedence
func **= (left: inout Double, right: Double) {
    left = left ** right
}

注意:这里的 left 是 inout 的,因为该赋值操作符改变了原来的值。

SwiftyColor 中的运算符

SwiftyColor 是一个通过数值快速生成颜色的库。其中自定义了 ~ 操作符来快速的给 Color 设置 alpha 值,自定义了 % 来表示一个百分数。

#if os(iOS)
  import UIKit
  public typealias Color = UIColor
#elseif os(OSX)
  import AppKit
  public typealias Color = NSColor
#endif

extension Int {
  public var color: Color {
    let red = CGFloat(self as Int >> 16 & 0xff) / 255
    let green = CGFloat(self >> 8 & 0xff) / 255
    let blue  = CGFloat(self & 0xff) / 255
    return Color(red: red, green: green, blue: blue, alpha: 1)
  }
}

precedencegroup AlphaPrecedence {
  associativity: left
  higherThan: RangeFormationPrecedence
  lowerThan: AdditionPrecedence
}

infix operator ~ : AlphaPrecedence

public func ~ (color: Color, alpha: Int) -> Color {
  return color ~ CGFloat(alpha)
}
public func ~ (color: Color, alpha: Float) -> Color {
  return color ~ CGFloat(alpha)
}
public func ~ (color: Color, alpha: CGFloat) -> Color {
  return color.withAlphaComponent(alpha)
}

/// e.g. `50%`
postfix operator %
public postfix func % (percent: Int) -> CGFloat {
  return CGFloat(percent)%
}
public postfix func % (percent: Float) -> CGFloat {
  return CGFloat(percent)%
}
public postfix func % (percent: CGFloat) -> CGFloat {
  return percent / 100
}

参考

nshipster.cn/swift-opera… www.jianshu.com/p/401527c77…