Comparing two enum variables regardless of their associated values

后端 未结 3 1478
野趣味
野趣味 2021-01-19 16:10

Consider this enum:

enum DataType {
    case One (data: Int)
    case Two (value: String)
}

Swift has pattern matching to compare an enum w

相关标签:
3条回答
  • 2021-01-19 16:37

    This worked for me:

    enum DataType {
        case one (data: Int)
        case two (value: String)
    }
    
    protocol EnumTypeEquatable {
        static func sameType(lhs: Self, rhs: Self) -> Bool
    }
    
    extension DataType: EnumTypeEquatable {
        static func sameType(lhs: DataType, rhs: DataType) -> Bool {
            if let caseLhs = Mirror(reflecting: lhs).children.first?.label, let caseRhs = Mirror(reflecting: rhs).children.first?.label {
                return (caseLhs == caseRhs)
            } else { return false }
        }
    }
    
    let isTypeEqual = DataType.sameType(lhs: .one(data: 1), rhs: .one(data: 2))
    print (isTypeEqual) // true
    
    0 讨论(0)
  • 2021-01-19 16:46

    Updated approach:

    I think there's no native support for this. But you can achieve it by defining a custom operator (preferrably by using a protocol, but you can do it directly as well). Something like this:

    protocol EnumTypeEquatable {
        static func ~=(lhs: Self, rhs: Self) -> Bool
    }
    
    extension DataType: EnumTypeEquatable {
        static func ~=(lhs: DataType, rhs: DataType) -> Bool {
            switch (lhs, rhs) {
            case (.one, .one), 
                 (.two, .two): 
                return true
            default: 
                return false
            }
        }
    }
    

    And then use it like:

    let isTypeEqual = DataType.One(value: 1) ~= DataType.One(value: 2)
    print (isTypeEqual) // true
    



    Old approach:

    protocol EnumTypeEquatable {
        var enumCaseIdentifier: String { get }
    }
    
    extension DataType: EnumTypeEquatable {
        var enumCaseIdentifier: String {
            switch self {
            case .one: return "ONE"
            case .two: return "TWO"
            }
        }
    }
    
    func ~=<T>(lhs: T, rhs: T) -> Bool where T: EnumTypeEquatable {
        return lhs.enumCaseIdentifier == rhs.enumCaseIdentifier
    }
    

    The older version depends on Runtime and might be provided with default enumCaseIdentifier implementation depending on String(describing: self) which is not recommended. (since String(describing: self) is working with CustromStringConvertible protocol and can be altered)

    0 讨论(0)
  • 2021-01-19 16:52

    Just confirm to Equatable like below

    extension DataType: Equatable {
        static func == (lhs: DataType, rhs: DataType) -> Bool {
            switch (lhs, rhs) {
            case (.One, .Two), (.Two, .One):
                return false
            case (.One, .One), (.Two, .Two):
                return true
            }
        }
    }
    

    If you don't want to implement Equatable just move content into instance method:

    extension DataType{
        func isSame(_ other: DataType) -> Bool {
            switch (self, other) {
            case (.One, .Two), (.Two, .One):
                return false
            case (.One, .One), (.Two, .Two):
                return true
            }
        }
    }
    

    Use:

    let isTypeEqual = DataType.One(value: 1).isSame(DataType.One(value: 2))
    print (isTypeEqual) // true
    
    0 讨论(0)
提交回复
热议问题