2015-01-09 102 views
14

我一直很难找到/理解如何比较Swift中的枚举的定义顺序的文档。特别是当我创建一个枚举如快速枚举的顺序和比较

enum EnumType { 
    case First, Second, Third 
} 

斯威夫特不允许我按订单直接比较枚举,如

let type1 = EnumType.First 
let type2 = EnumType.Second 
if type1 < type2 {println("good")} // error 

它生成的编译错误“不能援引‘<’与参数列表{EnumType,EnumType}的类型。所以,我已经找到了唯一的解决办法就是写我自己的比较操作过载,如

enum EnumType : Int { 
    case First = 0, Second, Third 
} 

func <(a: EnumType, b: EnumType) -> Bool { 
    return a.rawValue < b.rawValue 
} 

let type1 = EnumType.First 
let type2 = EnumType.Second 
if type1 < type2 {println("good")} // Returns "good" 

这是一个好一个对于在我的应用程序中具有很多用途和价值的“重量级”枚举有好处,但是对于我可能想要使用的所有操作符来说,重载过度似乎对于我可能定义的“轻量级”枚举过于繁琐,以便为某些命令一个小模块的常量。

有没有办法做到这一点,而无需为我在项目中定义的每个枚举类型编写大量的样板重载代码?更妙的是,有什么我错过让Swift自动提供比较运算符的简单枚举没有关联类型,即。是无类型的还是输入为Int? Swift知道如何比较Ints,为什么它不能比较枚举Ints?

+1

您可以使用'hashValue'属性,如[本答案](http://stackoverflow.com/a/27094973/148357)中所述。请务必阅读最后一条语句:) – Antonio 2015-01-09 21:28:41

回答

35

只要你给你的枚举一个基础类型,它将符合协议RawRepresentable

这意味着你可以写任何类型的原料可表示一个通用的比较操作,并具有原始类型,它是相当的,就像这样:

func <<T: RawRepresentable where T.RawValue: Comparable>(a: T, b: T) -> Bool { 
    return a.rawValue < b.rawValue 
} 

这将意味着你的枚举将自动获得一个<运营商:

enum E: Int { // this would work with Double and String also 
    // btw, no need to give a seed value of 0, 
    // that happens automatically for Ints 
    case A, B, C, D, E 
} 

E.A < E.C // returns true 

的样板,你仍然必须做的唯一的一点是你的标签如枚举在Comparable如果你想与需要泛型算法使用的是:

extension E: Comparable { } 
// (no need for anything else - requirements are already fulfilled) 

let a: [E] = [.C, .E, .A] 
let b = sorted(a) 
// b will now be [.A, .C, .E] 

使之符合Comparable也会给它<=>,和>=运营商自动地(通过标准库提供)。

+7

或者您可以将enum编写为enum E:Int,Comparable {..}没有任何意义可以随机添加延长线,IMO。 – 2016-05-03 17:35:20

+0

此方法是否返回字符串枚举的正确顺序(例如“Z”,情况“A”)?我建议,比较运算符会返回“Z”>“A”,这对我们的情况是不正确的。 – brigadir 2016-07-22 13:36:45

6

这在某种程度上与OP提出的自己的答案相同。它确实包含了你想要比较的每个枚举的一些样板代码,但是我更喜欢这个,而不是具有一些与所有枚举相媲美的外部魔术函数。如果你从一个程序快速复制并粘贴到另一个程序,那么这可能会导致问题,然后枚举不起作用,你不记得原因。

public enum LogLevel: Int, Comparable { 
    case verbose 
    case debug 
    case info 
    case warning 
    case error 
    case severe 

    // Implement Comparable 
    public static func < (a: LogLevel, b: LogLevel) -> Bool { 
     return a.rawValue < b.rawValue 
    } 
} 

编辑:

这是响应由@JasonMoore评论。

可比较不需要==。这是Equatable所要求的,Swift标准库为大多数枚举自动提供Equatable。

http://www.jessesquires.com/blog/swift-enumerations-and-equatable/

至于>,< =和> =,苹果的文件说,他们被要求相媲美,但是默认的实现提供了(根据使用==和<的,我假设) 。

https://developer.apple.com/documentation/swift/comparable

下面是一些代码,我在IBM斯威夫特沙箱跑了 - 它编译和运行良好上述定义。

let a : LogLevel = LogLevel.verbose 
let b : LogLevel = LogLevel.verbose 
let c : LogLevel = LogLevel.warning 

print(a == b) // prints true 
print(a > c) // prints false 
print(a <= c) // prints true 
+1

您需要添加方法'<=', '> ='和'>'以符合Comparable。这是一个令人讨厌的样板。 – 2017-05-10 19:05:21

+1

@JasonMoore请参阅我已添加的修改。 – RenniePet 2017-06-20 23:55:41

+2

你是对的。 “Equatable”会自动添加到枚举中(除非您有一个带变量的枚举类型)。你可以通过执行'<'来符合Comparable。谢谢澄清。 (我应该删除我的评论吗?) – 2017-06-21 13:21:22