Swift类如何自动实现Hashable?自定义扩展遇Equatable报错求解
关于类实现Hashable的两个问题及解决方案
每次给类实现Hashable时,我都会重复复制这段代码:
func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) } static func ==(lhs: Node, rhs: Node) -> Bool { return ObjectIdentifier(lhs) == ObjectIdentifier(rhs) }
利用ObjectIdentifier的唯一性实现引用相等,这种方式在社区里很常见,但我有两个疑问:
1. 为什么类不能像结构体一样自动隐式实现Hashable?
结构体是值类型,Swift默认会根据所有存储属性自动生成Equatable和Hashable的实现——比较时逐一对比成员属性,哈希时结合所有成员的哈希值。
而类是引用类型,Swift没有默认提供自动实现,核心原因是"相等"的定义对引用类型不唯一:有时候需要判断两个引用是否指向同一个对象(引用相等),有时候需要判断对象内容是否一致(值相等)。如果Swift自动给类实现Hashable,会强制使用单一规则,反而不符合开发者的多样化需求,因此把选择权交给了开发者自己。
2. 如何编写扩展自动为类实现Hashable?
你之前写的代码存在两个关键问题:
- 自定义的
ClassHash协议没有继承Hashable(及其父协议Equatable),编译器无法识别它与Hashable的关联; ==方法的参数类型是ClassHash协议类型,而Equatable要求==的两个参数必须是Self类型(即具体的类本身),这会导致编译器判定你未满足Equatable的要求。
正确的实现方式是让自定义协议继承Hashable和AnyObject,然后在扩展里用Self作为参数实现==和hash(into:):
protocol ReferenceHashable: Hashable, AnyObject {} extension ReferenceHashable { func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) } static func == (lhs: Self, rhs: Self) -> Bool { ObjectIdentifier(lhs) == ObjectIdentifier(rhs) } }
使用时,只需让类遵循ReferenceHashable协议即可:
class Node: ReferenceHashable { // 类的自定义内容 }
这样编译器就能正确识别类满足Hashable和Equatable的要求,无需再手动重复编写那两段代码。
内容的提问来源于stack exchange,提问作者johnbakers
相关产品推荐
相关产品推荐

