【问题标题】:How to conform custom class with optional properties to "hashable" protocol如何使具有可选属性的自定义类符合“可散列”协议
【发布时间】:2017-08-02 22:27:22
【问题描述】:

假设我有一个基类“Person”,我想将它添加到集合(列表)中,因此需要符合 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 个或更多可选属性怎么办?我可以看到这很快就会失控。

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

【问题讨论】:

    标签: swift optional hashable


    【解决方案1】:

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

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

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

    【讨论】:

    • 听起来很合理。也许是一个单独讨论的主题,但是:降低 hashValue 计算的特异性是否有任何不利之处,可能会在未来引起问题?
    • 在集合中存储对象时,哈希值不佳可能会导致性能问题。
    • hashValue 也可以用于== 的优化,当== 很昂贵时。如果它们的哈希值不相等,您可以快速丢弃明显不相等的值。 hashValue 应该是 O(1) 来计算。
    • @RobNapier 聪明!说得通。感谢您的额外提示。
    【解决方案2】:

    只想补充一点,一个类不需要遵守 Hashable 或 Equatable 协议即可用作 Array 的元素(我假设您是 List 的意思)。如果要将类用作 Set 中的元素或用作 Dictionary 的键,则只需要符合 Hashable 和 Equatable 的要求。如API reference of Hashable中指定:

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

    【讨论】:

    • 如果要使用index(of:)contains 等方法在数组中查找对象,则需要遵守Equatable。
    • 是的,为方便起见,如果您想避免将闭包传递给 index(of:)contains 而只传递元素本身。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    • 2020-08-16
    • 1970-01-01
    相关资源
    最近更新 更多