4

假设我有一个基类“Person”,我想将它添加到 Set(List)中,因此需要符合 Hashable 和 Equatable:

class Person : Equatable, Hashable {
let firstName: String
let lastName: String
var nickname: String?
let dateOfBirth: NSDate
var hashValue: Int {
    if let nickname = nickname {
        return firstName.hashValue ^
               lastName.hashValue ^
               nickname.hashValue ^
               dateOfBirth.hashValue
    } else {
        return firstName.hashValue ^
               lastName.hashValue ^
               dateOfBirth.hashValue
    }

}

init (firstName: String, lastName: String, nickname: String, bornOn dateOfBirth: NSDate) {
    self.firstName = firstName
    self.lastName  = lastName
    self.nickname = nickname
    self.dateOfBirth = dateOfBirth
    }
}

func ==(lhs: Person, rhs: Person) -> Bool {
    return
        lhs.firstName   == rhs.firstName    &&
        lhs.lastName    == rhs.lastName     &&
        lhs.nickname    == rhs.nickname     &&
        lhs.dateOfBirth == rhs.dateOfBirth
}

该类只有一个可选属性,这使得在创建哈希值时处理可选属性相当合理。如果有 2 个或更多可选属性怎么办?我可以看到这很快就会失控。

在使对象符合可散列协议时,通常如何处理可选属性?

4

2 回答 2

7

哈希值的计算不必基于所有属性。事实上,它不需要基于任何东西。您可以简单地返回一个硬编码的数字,尽管您不应该这样做。

只需返回一个或多个非可选属性的哈希值。

唯一的规则是两个比较相等的对象也必须返回相同的哈希值。但是没有要求具有相同哈希值的两个对象在比较时是相等的。

于 2017-03-13T00:11:11.203 回答
0

只是想补充一点,一个类不需要符合 Hashable 或 Equatable 协议即可用作数组的元素(这就是我假设您所说的 List 的意思)。如果要将类用作 Set 中的元素或用作 Dictionary 的键,则只需要符合 Hashable 和 Equatable 的要求。如Hashable 的 API 参考中所述

您可以在集合中使用任何符合 Hashable 协议的类型或作为字典键。

于 2017-03-13T00:50:18.373 回答