Swift中枚举遵循Equatable协议:未遵循Hashable时如何实现相等判断方法
Swift枚举遵循Equatable协议的疑问:hashValue访问权限与手动实现相等判断
问题描述
我写了一段让枚举显式遵循Equatable协议的代码:
enum TestEnum: Equatable { case one, two, three, four, five static func ==(lhs: TestEnum, rhs: TestEnum) -> Bool { return lhs.hashValue == rhs.hashValue } }
这里我用hashValue来做相等判断,但我有个疑问:我并没有让这个枚举遵循Hashable协议,为什么可以直接访问hashValue?
我的核心问题是:如果我的枚举只遵循Equatable、不遵循Hashable,而且无法访问hashValue的情况下,该怎么手动实现==方法来判断两个枚举值是否相等?
解答
1. 为什么没显式遵循Hashable却能访问hashValue?
在Swift中,没有关联值的枚举会被编译器自动赋予Equatable和Hashable的合成实现——哪怕你只显式声明了Equatable,编译器也会隐式地让它同时遵循Hashable协议。这是因为对于这类简单枚举,每个case都是唯一且可哈希的,编译器可以自动完成所有必要的实现,包括生成hashValue(在Swift 5.1及以后版本中是hash(into:)方法)。
所以你的TestEnum虽然只写了: Equatable,但实际上已经隐式遵循了Hashable,自然就能访问hashValue了。
2. 仅遵循Equatable时,如何手动实现==方法?
首先要明确:对于无关联值的枚举,你完全不需要手动实现==方法——编译器会自动为你合成正确的相等判断逻辑,直接写下面的代码就足够了:
enum TestEnum: Equatable { case one, two, three, four, five }
如果出于学习或特殊需求一定要手动实现,有两种直观的方式:
方式一:通过switch匹配枚举case组合
enum TestEnum: Equatable { case one, two, three, four, five static func ==(lhs: TestEnum, rhs: TestEnum) -> Bool { switch (lhs, rhs) { case (.one, .one), (.two, .two), (.three, .three), (.four, .four), (.five, .five): return true default: return false } } }
方式二:针对单个枚举case逐一判断
enum TestEnum: Equatable { case one, two, three, four, five static func ==(lhs: TestEnum, rhs: TestEnum) -> Bool { switch lhs { case .one: return rhs == .one case .two: return rhs == .two case .three: return rhs == .three case .four: return rhs == .four case .five: return rhs == .five } } }
如果你的枚举带有关联值,手动实现==时需要同时匹配case和关联值(关联值需遵循Equatable才能直接比较):
enum TestEnum: Equatable { case number(Int) case text(String) static func ==(lhs: TestEnum, rhs: TestEnum) -> Bool { switch (lhs, rhs) { case let (.number(left), .number(right)) where left == right: return true case let (.text(left), .text(right)) where left == right: return true default: return false } } }
内容的提问来源于stack exchange,提问作者user17958761
相关产品推荐
相关产品推荐

