首先我们定义一个结构体
struct Point {
var x = 0.0
var y = 0.0
}
当 Point 的两个变量相加时,我们需要这样做:
let p1 = Point(x: 1.0, y: 2.0)
let p2 = Point(x: 4.0, y: 3.0)
let p3 = Point(x: p1.x + p2.x, y: p1.y + p2.y)
如果这样的运算用到多次的话会显得很麻烦,swift提供了类似C++的操作符重载方法,下面实现一个 + 运算符的重载。
func + (left: Point, right: Point) -> Point {
returnPoint(x: left.x + right.x, y: left.y + right.y)
}
这样,就让这个相加运算跟基本类型的写法一致了。
let p1 = Point(x: 2.0, y: 3.0)
let p2 = Point(x: 1.0, y: 2.0)
let p3 = p1+p2
重载操作使运算变得简单,但 swift 有规定:等号运算符 = 和三木运算符 (a ? b : c) 不可被重载。
当标准的操作符不满足我们的要求时,我们就可用自定义一些操作符。
新的操作符需要用 operator 关键字声明在全局变量中,可以用 prefix,infix,postfix 声明
例如:
prefix operator, infix operator和 postfix operator⋅ {}
现在我们定义一个新的操作符 ⋅ 使结构体 Point 做相乘
infixoperator • {
associativity none
precedence 160
}
infix —> 表示定义的是一个双目操作符
prefix —> 表示定义一个左操作符,如取反操作符!
postfix —> 表示定义一个右操作符,如a++
associativity
定义了结合律,即如果多个同类的操作符顺序出现的计算顺序。比如常见的加法和减法都是left,就是说多个加法同时出现时按照从左往右的顺序计算(因为加法满足交换律,所以这个顺序无所谓,但是减法的话计算顺序就很重要了)。点乘的结果是一个Double,不再会和其他点乘结合使用,所以这里写成none;详见:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_65
precedence
运算的优先级,越高的话优先进行计算。swift 中乘法和除法的优先级是 150 ,加法和减法的优先级是 140 ,定义点积的优先级为 160 ,就是说应该早于普通的乘除进行运算。
func • (left: Point, right: Point) -> Double {
return left.x * right.x + left.y + right.y;
}
let value = v1 ⋅ v2 // 23.0
这样就可以进行点积运算了。
Equatable,和Comparable协议
在说Equatable之前,我们先实现上面Point的 == 运算。如下:
func == (left:Point, right: Point) -> Bool {
return left.x==right.x && left.y == right.y
}
这样,我们同样就可以使用 == 来判断两个Point变量是否相等了,如:
let v4 = Point(x: 2.0, y: 3.0)
let rst = v1==v4 //yes
然后,我们又想实现 != 运算,如:
func != (left:Point, right: Point) -> Bool {
return !(left == right)
}
然后,假设我们又依次去实现了 ‘>=‘ ,‘<=‘, ‘<‘,’>’等运算
这样显得太麻烦了。其实这些运算只要实现了其中的一个,那其他的都可以根据这个来进行取反或其他的操作来得到想要的结果,好在swift提供了两个协议:Equatable, Comparable。
只要遵循Equatable协议,并实现 '=='方法,那么自动的 '!=‘也就生成了,无需我们手动再重载。
Comparable协议继承于Equatable协议,且定义了它自身的规则。遵循Comparable后,必须实现小于号(“<“)操作符,然后再实现Equatable协议的是否等于(”==“)方法。实现了这两个方法之后,“>”, “>=“, “<=”等方法也会自动生成。
如下:
struct Point :Comparable{ //遵循了Comparable也同时遵循了Equatable协议
var x = 0.0
var y = 0.0
}
func == (left:Point, right: Point) -> Bool {
return left.x==right.x && left.y == right.y
}
func < (left:Point, right: Point) -> Bool {
returnpow(left.x, 2)+pow(left.y,2) < pow(right.x, 2) + pow(right.y, 2)
}
这样,我们就相当于把所有方法实现了。
总结:
swift的运算符重载是从C++中引入的,如果能够灵活使用的话,可以给编程带来很多便利。