swift - 避免 Equatable 和 Hashable 样板,Swift 4.2

标签 swift swift4.2 equatable

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

// 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)
    }
}

能否以某种方式避免这种样板文件?默认情况下,是否可以通过 .hashValue 实现 Equatable 比较?谢谢。

最佳答案

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

static func == (lhs: Player, rhs: Player) -> Bool {
    return lhs.hashValue == rhs.hashValue
}

相同的对象必须具有相同的哈希值,但反之则不然:不同的对象可以具有相同的哈希值。

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

如果所有存储的属性都是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)
    }
}

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

关于swift - 避免 Equatable 和 Hashable 样板,Swift 4.2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56540092/

相关文章:

swift - 将结构数组从 UICollectionView 传递到 DetailView 并使用索引从一项转到另一项?

ios - 向 UICollectionViewCell 添加覆盖 View - 保持覆盖

ios - 仅在 Swift 4.2 中上传包含多部分表单数据的图像

ios - 由于未捕获的异常 'NSInvalidArgumentException' 终止应用程序,原因 : '-[ABDC. 文件encodeWithCoder:]:

ios - 向下拖动以关闭ViewController

swift - 为什么 NSURL 上的这个可失败初始化器(采用可选字符串)无法编译?

cocoa - NSTableView - 使用 NSSortDescriptor 对集合进行排序的更好解决方案

swift - 在两个协议(protocol)对象上使用 equals

swift - Dictionary 在 Swift 中如何使用 Equatable 协议(protocol)?

Swift Struct 不符合协议(protocol) Equatable?