比较忽略关联值的Swift Enum类型 - 通用实现

问题描述 投票:5回答:2

我的项目中有几个不同的枚举,符合相同的协议。协议中的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"
}

在我的真实项目中,我有两个以上的枚举,并且对于每个枚举,我必须有类似的compareEnumType函数的实现。

问题是:是否有可能有一个compareEnumType的通用实现,它适用于符合EquatableEnumType协议的所有枚举?

我尝试在协议扩展中编写一个默认实现,如下所示:

extension EquatableEnumType {
    static func compareEnumType(lhs: Self, rhs: Self) -> Bool {
        // how to implement???
    }
}

但我坚持实施。我没有看到访问lhsrhs中包含的值的方法。谁能帮助我?

swift enums swift-protocols
2个回答
0
投票

我不认为你可以自动生成这个,所以这是一种使用扩展的方式。我建议创建一个新的enum CompareEnumMethod,告诉你是否要比较相关的values或只有type。在您的协议中创建一个新函数compareEnum,该函数将此枚举作为参数。然后,你可以为==(lhs:,rhs:)创建一个扩展,并说它使用.value,而对于compareEnumType,你使用.type。现在只需要在每个枚举中实现compareEnum方法。

enum CompareEnumMethod {
    case type, value
}

protocol EquatableEnumType: Equatable {
    static func compareEnumType(lhs: Self, rhs: Self) -> Bool
    static func compareEnum(lhs: Self, rhs: Self, method: CompareEnumMethod) -> Bool
}

extension EquatableEnumType {
    static func compareEnumType(lhs: Self, rhs: Self) -> Bool {
        return Self.compareEnum(lhs: lhs, rhs: rhs, method: .type)
    }

    static func ==(lhs: Self, rhs: Self) -> Bool {
        return Self.compareEnum(lhs: lhs, rhs: rhs, method: .value)
    }
}

enum MyEnum: EquatableEnumType {
    case A(Int)
    case B

    static func compareEnum(lhs: MyEnum, rhs: MyEnum, method: CompareEnumMethod) -> Bool {
        switch (lhs, rhs, method) {
        case let (.A(lhsA), .A(rhsA), .value):
            return lhsA == rhsA
        case (.A, .A, .type),
             (.B, .B, _):
            return true
        default:
            return false
        }
    }
}

let a0 = MyEnum.A(5)
let a1 = MyEnum.A(3)
let b0 = MyEnum.B
print(MyEnum.compareEnumType(lhs: a0, rhs: a1)) //true
print(a0 == a1) //false
print(MyEnum.compareEnumType(lhs: a0, rhs: b0)) //false

0
投票

简单!我会使用一个实例方法,但你可以将它重写为类函数,如果你真的需要它是静态的。

extension EquatableEnumCase {
    func isSameCase(as other: Self) -> Bool {
        let mirrorSelf = Mirror(reflecting: self)
        let mirrorOther = Mirror(reflecting: other)
        if let caseSelf = mirrorSelf.children.first?.label, let caseOther = mirrorOther.children.first?.label {
            return (caseSelf == caseOther) //Avoid nil comparation, because (nil == nil) returns true
        } else { return false}
    }
} 


enum MyEnum1: EquatableEnumCase {
    case A(Int)
    case B
}

enum MyEnum2: EquatableEnumCase {
    case X(String)
    case Y
}

let a = MyEnum1.A(5)
let a1 = MyEnum1.A(3)
if a.isSameCase(as: a1) {
    print("equal") // -> true, prints "equal1"
}

let x = MyEnum2.X("table")
let x1 = MyEnum2.X("chair")

if x.isSameCase(as: x1) {
    print("equal2") // -> true, prints "equal2"
}

let y = MyEnum2.Y
print(x.isSameCase(as: y) ? "equal3": "not equal3") // -> false, "not equal3"
© www.soinside.com 2019 - 2024. All rights reserved.