在项目中,我们将类用于模型的图层,因此,我必须编写如下代码:
// MARK: - Hashable
extension Player: Hashable {
static func == (lhs: Player, rhs: Player) -> Bool {
return lhs.hashValue == rhs.hashValue
}
func hash(into hasher: inout Hasher) {
hasher.combine(self.name)
}
}
可以以某种方式避免这种样板吗?默认情况下是否可以实现Equatable
与.hashValue
进行比较?谢谢。
答案 0 :(得分:4)
这是错误的,并且编译器自动合成它是没有意义的:
static func == (lhs: Player, rhs: Player) -> Bool {
return lhs.hashValue == rhs.hashValue
}
相同的对象必须具有相同的哈希值,但不能相反:不同的对象可以具有相同的哈希值。
在您的示例中,具体来说:名称是一个字符串,并且有无限多个不同的字符串,但是只有2 64 个不同的哈希值。因此,必须有两个具有相同哈希值的不同字符串。
如果所有存储的属性均为Hashable
,则编译器可以为您完整地合成一致性。例如
struct Player : Equatable, Hashable {
let name: String
var score: Int
}
如果两个球员的姓名和分数相同,则他们是“相同的”。
如果存在不可散列的属性,或者要自定义身份概念,则必须相应地覆盖==
和 hash(into)
。哈希函数应使用与确定==
中的身份相同的属性。例如
struct Player : Equatable, Hashable {
let name: String
var score: Int
static func == (lhs: Player, rhs: Player) -> Bool {
return lhs.name == rhs.name
}
func hash(into hasher: inout Hasher) {
hasher.combine(self.name)
}
}
现在,如果两个球员的名字相同,那么他们是“相同的”。
答案 1 :(得分:0)
您可以通过Stencil标记语言编写自定义模板,并使用Sourcery库自动生成代码。
或使用现有解决方案(AutoEquatable,AutoHashable Sourcery模板)。
您也可以这样写:
protocol IHash: class { }
extension IHash where Self: Hashable {
static func ==(lhs: Self, rhs: Self) -> Bool {
return lhs.hashValue == rhs.hashValue
}
}
class User: IHash, Hashable {
var name: String = ""
func hash(into hasher: inout Hasher) {
hasher.combine(self.name)
}
}
它将帮助您避免在不同的班级重复。