最近被人问到了swift运算符的自定义和重写,结果一时也就想了一个大概,所以,现在复习一下相关的实现,并做下笔记。
1、运算符的类型
swift里面的运算符有三种,分为infix,prefix,postfix
infix,即普通的 +、-、*、/。
prefix,像逻辑运算!a
postfix,比如 自增运算符i++
2、运算符自定义
在写法上,运算符的定义方式和普通函数方法相同,如果是将运算符函数作为一个类、struct的方法,则需要定义为static方法。
假如我们有一个Counter类,定义如下:
class Counter {
var count = 0
init(count: Int) {
self.count = count
}
}
- infix 运算符自定义,给counter类定义一个运算符+++,用来对Counter里面的count相加:
infix operator +++ : AdditionPrecedence
extension Counter {
static func +++(left: Counter, right: Counter) -> Int {
return (left.count + right.count)
}
}
定义一个运算符之前,需要先声明需要定义的方法。这里,声明+++ 运算符为infix operator,而AdditionPrecedence则表示该运算符所属的优先级族群。比如+ 和 * 运算符,+ 所属的优先级为AdditionPrecedence, 而所属的优先级为MultiplicationPrecedence。而MultiplicationPrecedence高于 AdditionPrecedence,所以一个表达式 1 + 2 3,会先计算* 。
除了系统自带的优先级族群,还可以自定义一个优先级族群,如下:
precedencegroup CustomePrecedence {
higherThan: AdditionPrecedence
lowerThan: MultiplicationPrecedence
associativity: right
}
其中, higherThan 和 lowerThan表示该自定义的优先级群的优先等级,对于CustomePrecedence这个优先级族群而言, 他的等级高于AdditionPrecedence,低于MultiplicationPrecedence。所以,他的计算应该是先于加法,落后于乘法。
associativity则表示计算的方向,可以是left 和right,对于一个表达式counter1 +++ counter2 +++ counter3
,如果associativity为left,那么就会先计算counter1 +++ counter2,如果是right,就会先计算counter2 +++ counter3。
- prefix 和 postfix 运算符自定义
定义prefix、postfix运算符和和定义infix一样,唯一的区别是不需要考虑优先级。
prefix operator <<<
prefix operator >>>
postfix operator %%
extension Counter {
static prefix func <<<(value: Counter) {
value.count += 2
}
static prefix func >>>(value: Counter) {
value.count -= 1
}
static postfix func %%(value: Counter) {
value.count = value.count % 2
}
}