如何testingSwift枚举与关联值的相等性
我想testing两个Swift枚举值的相等性。 例如:
enum SimpleToken { case Name(String) case Number(Int) } let t1 = SimpleToken.Number(123) let t2 = SimpleToken.Number(123) XCTAssert(t1 == t2)
但是,编译器不会编译相等expression式:
error: could not find an overload for '==' that accepts the supplied arguments XCTAssert(t1 == t2) ^~~~~~~~~~~~~~~~~~~
我有定义自己的等于运算符的重载吗? 我希望Swift编译器能够自动处理它,就像Scala和Ocaml一样。
正如其他人所指出的那样,Swift不会自动合成必要的相等运算符。 但是,让我提出一个更清洁的(恕我直言)实施:
enum SimpleToken: Equatable { case Name(String) case Number(Int) } public func ==(lhs: SimpleToken, rhs: SimpleToken) -> Bool { switch (lhs, rhs) { case let (.Name(a), .Name(b)), let (.Number(a), .Number(b)): return a == b default: return false } }
这很不理想 – 有很多重复 – 但是至less你不需要用if语句嵌套开关。
似乎没有编译器为枚举生成等于运算符,也不为结构生成。
“例如,如果您创build自己的类或结构来表示一个复杂的数据模型,则该类或结构的”等于“的含义不是Swift可以为您猜测的。”[1]
为了实现平等比较,可以写下如下的内容:
@infix func ==(a:SimpleToken, b:SimpleToken) -> Bool { switch(a) { case let .Name(sa): switch(b) { case let .Name(sb): return sa == sb default: return false } case let .Number(na): switch(b) { case let .Number(nb): return na == nb default: return false } } }
这是另一种select。 除了通过使用if case
语句来避免嵌套的switch语句之外,它和其他语言一样。 我认为这使得它稍微更具可读性(/ bearable),并具有完全避免默认情况的优点。
enum SimpleToken: Equatable { case Name(String) case Number(Int) } extension SimpleToken { func isEqual(st: SimpleToken)->Bool { switch self { case .Name(let v1): if case .Name(let v2) = st where v1 == v2 { return true } case .Number(let i1): if case .Number(let i2) = st where i1 == i2 { return true } } return false } } func ==(lhs: SimpleToken, rhs: SimpleToken)->Bool { return lhs.isEqual(rhs) } let t1 = SimpleToken.Number(1) let t2 = SimpleToken.Number(2) let t3 = SimpleToken.Name("a") let t4 = SimpleToken.Name("b") t1 == t1 // true t1 == t2 // false t3 == t3 // true t3 == t4 // false t1 == t3 // false
我在unit testing代码中使用了这个简单的解决方法:
extension SimpleToken: Equatable {} func ==(lhs: SimpleToken, rhs: SimpleToken) -> Bool { return String(stringInterpolationSegment: lhs) == String(stringInterpolationSegment: rhs) }
它使用string插值来执行比较。 我不会推荐它用于生产代码,但它是简洁的,并为unit testing工作。