Equatable, Hashable与Comparable
1年前 • 781次点击 • 来自 移动端
标签: Swift
Equatable, Hashable与Comparable是笔者高频使用到的3个协议,且它们3者有类似的功能,相关联度较高,故在此进行学习小结
- Equatable 判断2个对象是否相等或不等(==/!=)
- Hashable 判断2个对象Hash值是否一样
- Comparable 比较2个对象大小
Hashable继承至Equatable,2者具有以下的充要关系:
- 2个对象相等,hash一定相等
- 2个对象hash相等,2者不一定相等
所以根据以上特性,假设在一个集合Set中,Swift判断新加入的对象是否重复,则先判断hash是否有重复,如果hash值没有重复则加入这个新对象,如果hash相等,那么调用Equatable的实现进行下一步对比。
1.Equatable, Hashable的自动合成(Automatic Synthesis)
Swift4.1之后,Equatable, Hashable的自动合成支持了自动合成,无需再实现相关方法。
struct Person: Equatable, Hashable {
var name: String
var gender: String
var age: Int
}
Swift自动合成类似如下:
struct Person: Equatable, Hashable {
var name: String
var gender: String
var age: Int
//此处省略!= 的实现
static func == (lhs: Person, rhs: Person) -> Bool {
return lhs.name == rhs.name && lhs.gender == rhs.gender && lhs.age == rhs.age
}
//var hashValue: Int 已弃用
func hash(into hasher: inout Hasher) {
hasher.combine(name)
hasher.combine(gender)
hasher.combine(age)
}
}
也就是说如果,我们需要实现自己的Equatable和Hashable规则,则按上例进行自定义即可。
当一个类实现了Equatable之后,你可以在集合中判断是否存在相同对象,最好用的地方就是你能将它使用在switch判断中:
let person0 = Person(name: "devler", gender: "male", age: 1)
let person1 = Person(name: "devler", gender: "male", age: 18)
let person2 = Person(name: "devler", gender: "male", age: 60)
[person0, person1, person2].contains(person0)
func age(for person: Person) -> String? {
switch person {
case person0: return "童雷"
case person1: return "少雷"
case person2: return "老雷"
default: return nil
}
}
age(for: person0)
2.Comparable
Comparable则不支持自动合成,它支持以下4个操作符:
操作符 | 解释 |
---|---|
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
所以如果我们需要对比2个对象的大小,只需要实现 < 方法:
static func < (lhs: Person, rhs: Person) -> Bool
例如:
extension Person: Comparable {
static func < (lhs: Person, rhs: Person) -> Bool {
if lhs.age != rhs.age {
return lhs.age < rhs.age
} else {
return lhs.name < rhs.name
}
}
}
let person0 = Person(name: "devler", gender: "male", age: 1)
let person1 = Person(name: "devler", gender: "male", age: 18)
let person2 = Person(name: "devler", gender: "male", age: 60)
person1 > person0
person1 > person2
实现了Comparable协议,我们就可以做排序和最大最小相关的操作:
var persons = [person1, person0, person2]
persons.sort()
persons.min()
persons.max()