Swift 自定义运算符

Swift 自定义运算符

1. 运算符

Swift 提供了一组对于 C 或者 Objective-C 开发者来说十分熟悉的运算符,并且补充了一些新的(特别需要注意的是,区间运算符和空值合并(nil coalescing)运算符):

如下面这些运算符

符号 -
+
-
*
/
%
+=: 赋值增
-=: 赋值减
*=: 赋值乘
/= 赋值除
!
~ 按位取反
…… ……

2. 重载

Swfit 是可以重载运算符的,其能够让现有的运算符像 + 在其它的类型中起作用。

为了重载一个运算符,需要为运算符号简单的定义一个新的函数,并且要有适当的参数个数。

例如,重载 * 来让一个字符串重复某个特定的次数:

func * (left: String, right: Int) -> String {
  
    if right <= 0 {
        return ""
    }
    var result = left
    for _ in 1..

然而,这是一个有争议的语言特性。

如下语句:

[1, 2] + [3, 4] // [1, 2, 3, 4]

两个数组相加,想得到 [1, 2, 3, 4],但重载以后:

func +(left: [Double], right: [Double]) -> [Double] {
   
    var sum = [Double](repeating: 0.0, count: left.count)
  
    for (i, _) in left.enumerated() {
        sum[i] = left[i] + right[i]
    }
    return sum
}

得到的是 [4.0, 6.0]

运算符重载的问题会造成:语意不清。在使用时,要注意具体应用,并避免重载。

  • 计算整数的和: 1 + 2 // 3
  • 计算浮点数的和: 1.0 + 2.0 // 3.0
  • 字符串连接: "a" + "b" // "ab"
  • 数组连接: ["foo"] + ["bar"] // ["foo", "bar"]

如果需要重载运算符要考虑多种情况,避免出现不可预见的bug.

3. 自定义运算符

自定义运算符,一般可以分三步

  • 1.定义优先级组

    如果需要自己设置优先级组,可以自己定义,使用precedencegroup关键字声明,如果不需要,可以省去。precedencegroup定义了一个操作符优先级别。操作符优先级的定义和类型声明有些相似,一个操作符比需要属于某个特定的优先级。Swift 标准库中已经定义了一些常用的运算优先级组,比如加法优先级 (AdditionPrecedence) 和乘法优先级 (MultiplicationPrecedence) 等,你也可以查看完整的列表。如果没有适合你的运算符的优先级组,你就需要像在例子中做的这样,自己指定方式和优先级顺序。

    precedencegroup CustomerPrecedence {
      /// 优先从左向右, left, right or none
      associativity: left
      higherThan: MultiplicationPrecedence//优先级,比乘法运算高
      // lowerThan: AdditionPrecedence // 优先级, 比加法运算低
      assignment: false // 是否是赋值运算
    }
    

    associativity
    定义了结合律,即如果多个同类的操作符顺序出现的计算顺序。比如常见的加法和减法都是 left

    higherThan
    运算的优先级,乘法运算是优先于加减运算的。除了 higherThan,也支持使用 lowerThan 来指定优先级低于某个其他组。

  • 2.设置优先级

    继承 CustomerPrecedence 优先级组,也可以继承已有优先级组 AdditionPrecedence等

    infix operator **: CustomerPrecedence 
    

    infix
    表示要定义的是一个中位操作符,即前后都是输入;其他的修饰子还包括 prefixpostfix,感兴趣的可以尝试一下;

  • 3.在扩展类里写实现,或者自定义类

    **运算符定义一个数的平方。

    extension Int {
    static func ** (lhs: Int, rhs: Int) -> Int {
        return Int(pow(Double(lhs), Double(rhs)))
     }
    }
    print(10**2)// 100
    
    

    字符串示例

    precedencegroup BLCustomerPrecedence {
    
      /// 优先从左向右, left, right or none
      associativity: left
      //    higherThan: MultiplicationPrecedence//优先级,比乘法运算高
      //    lowerThan: AdditionPrecedence       // 优先级, 比加法运算低
      assignment: false                   // 是否是赋值运算
      }
    
    infix operator ~~: BLCustomerPrecedence
    
    extension String {
    
      static func ~~ (left: String, right: String) -> String {
             return left + right
        }
    }
    print("12112"~~"~~")
    

    便捷写法:

    求一个数的平方根

    prefix operator √ // 默认 左->右 的优先级
    prefix func √ (number: Double) -> Double {
           return sqrt(number)
    }
    √4  // 2
    

需要注意的是,Swift 的操作符必须是全局部的,用static修饰。这就可能与其他 module 定义的操作符有冲突,这点需要特别注意。自定义操作符应该尽量避免重载,应简尽简,切禁写的太复杂,命名尽量规范,避免误解。

你可能感兴趣的:(Swift 自定义运算符)