我想测试两个Swift enum值的相等性。例如:

enum SimpleToken {
    case Name(String)
    case Number(Int)
}
let t1 = SimpleToken.Number(123)
let t2 = SimpleToken.Number(123)
XCTAssert(t1 == t2)

但是,编译器不会编译等式表达式:

error: could not find an overload for '==' that accepts the supplied arguments
    XCTAssert(t1 == t2)
    ^~~~~~~~~~~~~~~~~~~

我需要自己定义重载的相等运算符吗?我希望Swift编译器能自动处理它,就像Scala和Ocaml那样。


当前回答

另一种选择是比较大小写的字符串表示:

XCTAssert(String(t1) == String(t2))

例如:

let t1 = SimpleToken.Number(123) // the string representation is "Number(123)"
let t2 = SimpleToken.Number(123)
let t3 = SimpleToken.Name("bob") // the string representation is "Name(\"bob\")"

String(t1) == String(t2) //true
String(t1) == String(t3) //false

其他回答

除了上面的答案之外,您还可以添加计算属性作为助手。这也是优化可读性的许多方法之一。

    enum UserAccountViewStack: Hashable {
        case notLoggedIn
        case initialDevicePairing
        case deviceMainView
        case leftMenu(LeftMenuStack? = nil)
        case rightMenu(RightMenuStack? = nil)

        static var `default`: Self {
            .deviceMainView
        }

        var isLeftMenu: Bool {
            if case .leftMenu = self {
                return true
            }
            return false
        }

        var isRightMenu: Bool {
            if case .rightMenu = self {
                return true
            }
            return false
        }
    }

从Swift 4.1中,只需将Equatable协议添加到您的枚举中,并使用XCTAssert或XCTAssertEqual:

enum SimpleToken : Equatable {
    case Name(String)
    case Number(Int)
}
let t1 = SimpleToken.Number(123)
let t2 = SimpleToken.Number(123)
XCTAssertEqual(t1, t2) // OK

我在单元测试代码中使用这个简单的解决方法:

extension SimpleToken: Equatable {}
func ==(lhs: SimpleToken, rhs: SimpleToken) -> Bool {
    return String(stringInterpolationSegment: lhs) == String(stringInterpolationSegment: rhs)
}

它使用字符串插值来执行比较。我不建议在生产代码中使用它,但是它很简洁,并且可以用于单元测试。

t1和t2不是数字,它们是带有关联值的simpletoken实例。

你可以说

var t1 = SimpleToken.Number(123)

你可以说

t1 = SimpleToken.Name(“Smith”) 

没有编译器错误。

要从t1中检索值,使用switch语句:

switch t1 {
    case let .Number(numValue):
        println("Number: \(numValue)")
    case let .Name(strValue):
        println("Name: \(strValue)")
}

另一种方法使用if大小写加逗号,在Swift 3中有效:

enum {
  case kindOne(String)
  case kindTwo(NSManagedObjectID)
  case kindThree(Int)

  static func ==(lhs: MyEnumType, rhs: MyEnumType) -> Bool {
    if case .kindOne(let l) = lhs,
        case .kindOne(let r) = rhs {
        return l == r
    }
    if case .kindTwo(let l) = lhs,
        case .kindTwo(let r) = rhs {
        return l == r
    }
    if case .kindThree(let l) = lhs,
        case .kindThree(let r) = rhs {
        return l == r
    }
    return false
  }
}

我是这样写我的项目的。但我不记得我是怎么想到的。(我刚刚谷歌了一下,但没有看到这样的用法。)任何意见都将不胜感激。