我想测试两个Swift枚举值的相等性.例如:
enum SimpleToken {
case Name(String)
case Number(Int)
}
let t1 = SimpleToken.Number(123)
let t2 = SimpleToken.Number(123)
XCTAssert(t1 == t2)
Run Code Online (Sandbox Code Playgroud)
但是,编译器不会编译相等表达式:
error: could not find an overload for '==' that accepts the supplied arguments
XCTAssert(t1 == t2)
^~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
我是否已经定义了我自己的等于运算符的重载?我希望Swift编译器能够自动处理它,就像Scala和Ocaml一样.
rad*_*dex 226
正如其他人所说,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
}
}
Run Code Online (Sandbox Code Playgroud)
它远非理想 - 有很多重复 - 但至少你不需要在内部使用if语句进行嵌套开关.
mbp*_*pro 54
实施Equatable
是一个矫枉过正的恕我直言.想象一下,你有许多案例和许多不同参数的复杂和大枚举.这些参数也都必须Equatable
实现.此外,谁说您在全有或全无的基础上比较枚举案例?如果您正在测试值并且仅存在一个特定的枚举参数,那该怎么办?我强烈建议简单的方法,如:
if case .NotRecognized = error {
// Success
} else {
XCTFail("wrong error")
}
Run Code Online (Sandbox Code Playgroud)
......或在参数评估的情况下:
if case .Unauthorized401(_, let response, _) = networkError {
XCTAssertEqual(response.statusCode, 401)
} else {
XCTFail("Unauthorized401 was expected")
}
Run Code Online (Sandbox Code Playgroud)
在此处查找更详细的说明:https://mdcdeveloper.wordpress.com/2016/12/16/unit-testing-swift-enums/
pai*_*aiv 14
对于枚举,结构似乎没有编译器生成的相等运算符.
"例如,如果您创建自己的类或结构来表示复杂的数据模型,则该类或结构的"等于"的含义不是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
}
}
}
Run Code Online (Sandbox Code Playgroud)
[1]请参阅https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_43上的 "等效运营商"
Dan*_*ood 14
这是另一种选择.除了通过使用if case
语法避免嵌套的switch语句之外,它主要与其他语句相同.我认为这使得它更具可读性(/可忍受)并且具有完全避免默认情况的优点.
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
Run Code Online (Sandbox Code Playgroud)
neo*_*eye 12
enum MyEnum {
case None
case Simple(text: String)
case Advanced(x: Int, y: Int)
}
func ==(lhs: MyEnum, rhs: MyEnum) -> Bool {
switch (lhs, rhs) {
case (.None, .None):
return true
case let (.Simple(v0), .Simple(v1)):
return v0 == v1
case let (.Advanced(x0, y0), .Advanced(x1, y1)):
return x0 == x1 && y0 == y1
default:
return false
}
}
Run Code Online (Sandbox Code Playgroud)
Nik*_*uhe 11
我在单元测试代码中使用这个简单的解决方法:
extension SimpleToken: Equatable {}
func ==(lhs: SimpleToken, rhs: SimpleToken) -> Bool {
return String(stringInterpolationSegment: lhs) == String(stringInterpolationSegment: rhs)
}
Run Code Online (Sandbox Code Playgroud)
它使用字符串插值来执行比较.我不推荐它用于生产代码,但它简洁并且可以完成单元测试.
Dan*_*iel 10
另一种选择是比较案例的字符串表示:
XCTAssert(String(t1) == String(t2))
Run Code Online (Sandbox Code Playgroud)
例如:
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
Run Code Online (Sandbox Code Playgroud)
扩展 mbpro 的答案,这是我如何使用该方法检查具有某些边缘情况的关联值的 swift 枚举的相等性。
当然,您可以执行 switch 语句,但有时只检查一行中的一个值也不错。你可以这样做:
// NOTE: there's only 1 equal (`=`) sign! Not the 2 (`==`) that you're used to for the equality operator
// 2nd NOTE: Your variable must come 2nd in the clause
if case .yourEnumCase(associatedValueIfNeeded) = yourEnumVariable {
// success
}
Run Code Online (Sandbox Code Playgroud)
如果要比较同一个 if 子句中的 2 个条件,则需要使用逗号而不是 &&
运算符:
if someOtherCondition, case .yourEnumCase = yourEnumVariable {
// success
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
66970 次 |
最近记录: |