Swift之Equatable和Comparable

自定义值类型实现Equatable协议,可以测试相等性;实现Comparable,可以测试可比性。

Equatable协议

Equatable协议指出,符合这个协议的类型应该有一个静态方法==;一旦一个类型通过实现自己的==符合了Equatable,也就有了!=函数。

1
2
3
4
5
6
7
8
9
10
11
12
struct Point:Equatable{
let x: Int
let y: Int
static func ==(point1: Point, point2: Point) -> Bool{
return (point1.x == point2.x) && (point1.y == point2.y)
}
}

let a = Point(x:3, y:4)
let b = Point(x:12, y:5)
let abEqual = (a==b)
let abNotEqual = (a!=b)

==声明为静态方法,但==的调用并不是在Point类型上,这时因为==这样的运算符在Swift中是定义在全局层面的。==在Swift标准库中的定义:

1
2
3
4
precedencegroup ComparisonPrecedence{
higherThan: LogicalConjunctionPrecedence
}
infix operator == : ComparisonPrecedence

Comparable

如果自定义值类型符合Comparable协议,跟符合Equatable协议相似,实现一个函数可以得到很多功能。Swift标准库用“<”和“==”运算符定义了“>”、“ >=”、“<=”运算。所以遵循Comparable协议,我们只需要实现“<”或“>”运算符,就会自动得到这些运算符的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct Point: Equatable,Comparable{
let x: Int
let y: Int
static func ==(point1: Point, point2: Point) -> Bool{
return (point1.x == point2.x) && (point1.y == point2.y)
}
static func <(point1: Point, point2: Point) -> Bool{
return (point1.x < point2.x) && (point1.y < point2.y)
}
}

let a = Point(x:3, y:4)
let b = Point(x:12, y:5)
let result1 = (a < b)
let result2 = (a <= b)
let result3 = (a > b)
let result4 = (a >= b)

Comparable 与 Equatable

实际上,Comparable继承于Equatable。所以,符合Comparable协议的类型,不需要显式声明符合Equatable,需要同时提供“==”的实现。

所以上面的Point遵守的协议只需要写Comparable一个就够了

1
2
3
struct Point: Comparable{

}