使用比较运算符扩展 Int 枚举

Extend Int enum with comparison operators

你经常有这样的 Int 枚举:

enum Difficulty: Int {
    case Easy = 0
    case Normal
    case Hard
}

Difficulty 值有一定的意义,我们可能想为它们引入顺序。比如某处我们需要比较:

let isBonusAvailable = level.difficulty.rawVAlue <= Difficulty.Hard.rawValue

我想让这段代码短一点:

let isBonusAvailable = level.difficulty <= .Hard

直接在Difficulty后面加上<=可以轻松实现。但是我想从总体上解决这个问题,所以我尝试了这种超级棘手的方法:

protocol RawRepresentableByInt {
    var rawValue: Int { get }
}

extension RawRepresentableByInt {
    static func <(lhs: RawRepresentableByInt, rhs: RawRepresentableByInt) -> Bool {
        return lhs.rawValue < rhs.rawValue
    }

    static func >(lhs: RawRepresentableByInt, rhs: RawRepresentableByInt) -> Bool {
        return lhs.rawValue > rhs.rawValue
    }

    static func <=(lhs: RawRepresentableByInt, rhs: RawRepresentableByInt) -> Bool {
        return lhs.rawValue <= rhs.rawValue
    }

    static func >=(lhs: RawRepresentableByInt, rhs: RawRepresentableByInt) -> Bool {
        return lhs.rawValue >= rhs.rawValue
    }
}

// Error: Extension of protocol 'RawRepresentable' cannot have an inheritance clause
extension RawRepresentable: RawRepresentableByInt where RawValue == Int  {
}

它产生一个编译器错误:

Error: Extension of protocol 'RawRepresentable' cannot have an inheritance clause

我觉得在逻辑上和Intenum相比,没有什么是无法实现的。请帮我欺骗 Swift 编译器。任何也需要此类扩展的人都可以参加。

这比我想象的要容易。所以,基本上你可以使用 Self 而不是创建一个额外的协议。

enum Difficulty: Int {
    case Easy = 0
    case Normal
    case Hard
}

extension RawRepresentable where RawValue: Comparable {
    static func <(lhs: Self, rhs: Self) -> Bool {
        return lhs.rawValue < rhs.rawValue
    }

    static func >(lhs: Self, rhs: Self) -> Bool {
        return lhs.rawValue > rhs.rawValue
    }

    static func <=(lhs: Self, rhs: Self) -> Bool {
        return lhs.rawValue <= rhs.rawValue
    }

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

let easy = Difficulty.Easy
print(easy > .Hard) // false