避免 Equatable 和 Hashable 样板,Swift 4.2

Boh*_*ych 1 swift equatable swift4.2

在项目中,我们将类用于模型层,因此我必须编写如下代码:

// 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

可以以某种方式避免这种样板吗?默认情况下是否可以实现该Equatable比较.hashValue?谢谢。

Mar*_*n R 6

这是错误的,编译器自动合成它是没有意义的:

static func == (lhs: Player, rhs: Player) -> Bool {
    return lhs.hashValue == rhs.hashValue
}
Run Code Online (Sandbox Code Playgroud)

相同的对象必须具有相同的散列值,但反过来不行:不同的对象可以具有相同的散列值。

具体来说,在您的示例中:名称是一个字符串,并且有无限多个不同的字符串,但只有 2 64 个不同的哈希值。所以一定有两个不同的字符串具有相同的哈希值。

如果所有存储的属性都是,Hashable那么编译器可以完全为您合成一致性。例如

struct Player : Equatable, Hashable {
    let name: String
    var score: Int
}
Run Code Online (Sandbox Code Playgroud)

在这里,如果两个玩家具有相同的名称和相同的分数,则他们是“相同的”。

如果有非哈希的属性,或者如果你想定制身份的概念,那么你必须覆盖== 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果两个玩家具有相同的名字,则他们是“相同的”。