【发布时间】:2017-12-01 16:26:28
【问题描述】:
我的项目中有几个不同的枚举,它们符合相同的协议。协议中的compareEnumType 方法比较忽略关联值的枚举案例。这是我在操场上的代码:
protocol EquatableEnumType {
static func compareEnumType(lhs: Self, rhs: Self) -> Bool
}
enum MyEnum: EquatableEnumType {
case A(Int)
case B
static func compareEnumType(lhs: MyEnum, rhs: MyEnum) -> Bool {
switch (lhs, rhs) {
case (.A, .A): return true
case (.B, .B): return true
default: return false
}
}
}
enum MyEnum2: EquatableEnumType {
case X(String)
case Y
static func compareEnumType(lhs: MyEnum2, rhs: MyEnum2) -> Bool {
switch (lhs, rhs) {
case (.X, .X): return true
case (.Y, .Y): return true
default: return false
}
}
}
let a = MyEnum.A(5)
let a1 = MyEnum.A(3)
if MyEnum.compareEnumType(lhs: a, rhs: a1) {
print("equal") // -> true, prints "equal"
}
let x = MyEnum2.X("table")
let x1 = MyEnum2.X("chair")
if MyEnum2.compareEnumType(lhs: x, rhs: x1) {
print("equal2") // -> true, prints "equal2"
}
在我的实际项目中,我有超过 2 个枚举,对于每个枚举,我都必须有类似的 compareEnumType 函数实现。
问题是:是否有可能有一个通用的compareEnumType 实现,它适用于所有符合EquatableEnumType 协议的枚举?
我尝试在协议扩展中编写一个默认实现,如下所示:
extension EquatableEnumType {
static func compareEnumType(lhs: Self, rhs: Self) -> Bool {
// how to implement???
}
}
但我坚持执行。我看不到访问lhs 和rhs 中包含的值的方法。谁能帮帮我?
【问题讨论】:
-
这违反了
Equatable的含义,它“暗示了可替换性——任何两个相等比较的实例都可以在取决于它们的值的任何代码中互换使用。为了保持可替换性,== 运算符应该考虑到 Equatable 类型的所有可见方面。不鼓励公开 Equatable 类型的非值方面而不是类标识,任何公开的方面都应在文档中明确指出。这是一个非常糟糕的主意,您应该重新设计您的类型以避免它。如果你决心这样做,你需要的工具就是 SwiftGen。 -
如果您的枚举携带与相等性无关的私有信息(例如缓存),那么您几乎可以肯定在这里使用类或结构。枚举不太适合该问题。 (任何基于枚举的解决方案都可以转换为基于协议+结构的等价物,反之亦然。维护权衡会有所不同,但逻辑始终可以实现,因为它们是对偶的。)
-
@RobNapier 我不想改变 == 的含义或实现。我知道它考虑了关联的值,这是正确的。在我的协议中,我只想比较枚举案例,而忽略关联的值。我尝试使用 == 但它对我不起作用(这是正确的)。我正在寻找另一种解决方案来比较如何以通用方式忽略关联值的枚举案例。
-
当然。资源。 github.com/krzysztofzablocki/Sourcery(抱歉之前说的是 SwiftGen;这是 Sourcery 所基于的低级库,但为此您需要 Sourcery)简短而长的答案是您需要 Swift 中不存在的元编程级别,这就是 Sourcery 目前填补空白的地方。有一天,Swift 中会出现更多元编程,因此不需要 Sourcery,但今天不是那一天。
-
(根据您的编辑,这没有任何问题,当然也有道理。只有将它与 Equatable 联系起来才是问题。)
标签: swift enums swift-protocols