问题缘起
Set 有个天然属性,就是放入的元素不能重复,这个特性也被常用于去除重复数据:
var set:Set = ["1", "2", "3", "4", "1", "1"]
print("set:\(set)") //输出为:set:["2", "1", "3", "4"]
系统类可以很方便地放入Set,那么自定义类呢?
假设需要自定义Person类,有个name属性,这里我们假设名字相同的人只有一个,所以逻辑上name相同的对象,在Set中只能有一个,但对于对象来说,两个实例是不同的指针,是不同的:
class Person {
var name:String
init(name:String) {
self.name = name
}
}
var x1:Person? = Person(name:"Xishi")
var x2:Person? = Person(name:"Xishi")
var set:Set<Person?> = [x1, x2]
实际上,以上代码无法通过编译:
'Set' requires that 'Person' conform to 'Hashable'
解决方案
Swift 要求放入Set的类实现Hashable
协议,而Hashable
本身又继承了Equatable
协议,所以这里要同时实现两个协议:
class Person : Hashable {
var name:String
init(name:String) {
self.name = name
}
public var hashValue : Int {
get {
return self.name.hashValue
}
}
static func ==(lhs: Person, rhs: Person) -> Bool {
return lhs.name == rhs.name
}
}
-
public var hashValue : Int
是Hashable协议要求的,需要返回能代表对象的哈希值,这里正好利用 String 的哈希值。 - 看起来怪怪的
static func ==(lhs: Person, rhs: Person) -> Bool
方法声明是运算符重载
,这里把==
当作方法名就好理解了,相当于替换了一个名叫==
的方法。
这样,放入Set后,就能正常去除重复对象了。
小实验
将 ==
方法改为固定返回 false,看看会发生什么,与你想象中一样吗?
网友评论