如何使具有可选属性的自定义 class 符合 "hashable" 协议
How to conform custom class with optional properties to "hashable" protocol
假设我有一个基础 class "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
}
这个class只有一个optional属性,这使得在创建hashvalue时对optional的处理相当合理。如果有 2 个或更多可选属性怎么办?我可以看到这很快就会失控。
在使对象符合可散列协议时,通常如何处理可选属性?
哈希值的计算不必基于所有属性。事实上,它不需要基于任何。你可以简单地 return 一个硬编码的数字,但你不应该这样做。
只是 return 一个或多个非可选属性的哈希值。
唯一的规则是比较相等的两个对象也必须 return 具有相同的散列值。但是不要求具有相同散列值的两个对象比较相等。
只想补充一点,class 不需要遵守 Hashable 或 Equatable 协议即可用作数组的元素(这就是我假设您所说的列表的意思)。如果您想将 class 用作 Set 中的元素或用作 Dictionary 的键,则只需要符合 Hashable 和 Equatable。如 API reference of Hashable 中指定:
You can use any type that conforms to the Hashable protocol in a set
or as a dictionary key.
假设我有一个基础 class "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
}
这个class只有一个optional属性,这使得在创建hashvalue时对optional的处理相当合理。如果有 2 个或更多可选属性怎么办?我可以看到这很快就会失控。
在使对象符合可散列协议时,通常如何处理可选属性?
哈希值的计算不必基于所有属性。事实上,它不需要基于任何。你可以简单地 return 一个硬编码的数字,但你不应该这样做。
只是 return 一个或多个非可选属性的哈希值。
唯一的规则是比较相等的两个对象也必须 return 具有相同的散列值。但是不要求具有相同散列值的两个对象比较相等。
只想补充一点,class 不需要遵守 Hashable 或 Equatable 协议即可用作数组的元素(这就是我假设您所说的列表的意思)。如果您想将 class 用作 Set 中的元素或用作 Dictionary 的键,则只需要符合 Hashable 和 Equatable。如 API reference of Hashable 中指定:
You can use any type that conforms to the Hashable protocol in a set or as a dictionary key.