Swift enum과 관련된 값의 동일성을 테스트하는 방법
두 Swift 열거값의 동일성을 테스트하고 싶습니다.예를 들어 다음과 같습니다.
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처럼 자동으로 처리해 주길 바랐습니다.
Swift 4.1 이상
@jedwidz가 지적한 바와 같이 Swift 4.1부터 (SE-0185를 통해 Swift는 합성도 지원합니다)Equatable
★★★★★★★★★★★★★★★★★」Hashable
enums ums 。
Swift 4.1 한 방법을 할 수 있습니다.XCTAssert(t1 == t2)
은 동 the the the the the 를 추가하는 것입니다. ★★★★★★★★★★★★★★★★,Equatable
suum.suffer.로 합니다.
enum SimpleToken: Equatable {
case Name(String)
case Number(Int)
}
let t1 = SimpleToken.Number(123)
let t2 = SimpleToken.Number(123)
Swift 4.1 이전
다른 사람들이 지적했듯이, Swift는 필요한 평등 연산자를 자동으로 합성하지 않습니다.다만, 클리너(IMHO)의 실장을 제안합니다.
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
}
}
이상과는 거리가 멀고 반복이 많지만 적어도 if-statement가 내장된 네스트 스위치를 실행할 필요는 없습니다.
★★의 Equatable
IMHO라고 . 큰, 가지 매개 변수가 해 보세요.복잡하고 큰 열거형과 많은 사례와 다양한 매개 변수가 있다고 가정해 보십시오. '다음에 있다'를 가지고 합니다.Equatable
구현되었습니다.게다가, 누가 열거형 사건들을 전부 아니면 전혀 비교하지 않는다고 했습니까?값을 테스트하고 특정 열거형 파라미터가1개밖에 없는 경우는 어떻습니까?다음과 같은 간단한 방법을 강력히 제안합니다.
if case .NotRecognized = error {
// Success
} else {
XCTFail("wrong error")
}
... 또는 파라미터 평가의 경우:
if case .Unauthorized401(_, let response, _) = networkError {
XCTAssertEqual(response.statusCode, 401)
} else {
XCTFail("Unauthorized401 was expected")
}
상세한 것에 대하여는, https://mdcdeveloper.wordpress.com/2016/12/16/unit-testing-swift-enums/ 를 참조해 주세요.
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
}
}
enum이나 structure에 대해 컴파일러가 생성한 등호 연산자는 없는 것 같습니다.
「예를 들면, 복잡한 데이터 모델을 나타내는 독자적인 클래스나 구조를 작성하는 경우, 그 클래스나 구조에 대해서 「동등」의 의미는 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
}
}
}
[1] https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html #//apple_ref/doc/uid/TP40014097-CH27-XID_43에서 "등가 연산자"를 참조하십시오.
여기 또 다른 선택지가 있습니다.이 명령어는 주로 다른 명령어와 동일합니다만,if case
구문을 사용합니다.이렇게 하면 조금 더 읽기 쉽고 디폴트 케이스를 완전히 피할 수 있는 장점이 있다고 생각합니다.
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
유닛 테스트코드에 다음과 같은 간단한 회피책을 사용하고 있습니다.
extension SimpleToken: Equatable {}
func ==(lhs: SimpleToken, rhs: SimpleToken) -> Bool {
return String(stringInterpolationSegment: lhs) == String(stringInterpolationSegment: rhs)
}
비교를 수행하기 위해 문자열 보간을 사용합니다.생산 코드로는 추천하지 않지만, 간결하고 유닛 테스트에도 도움이 됩니다.
또 다른 옵션은 다음과 같은 케이스의 문자열 표현을 비교하는 것입니다.
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
mbpro의 답변에 대해 자세히 설명하자면, 이 접근방식을 사용하여 일부 엣지 케이스와 관련된 값과 신속한 Enum이 동일한지 여부를 확인합니다.
물론 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
}
같은 if 절의 두 조건을 비교하려면 comma 대신 쉼표를 사용해야 합니다.&&
연산자:
if someOtherCondition, case .yourEnumCase = yourEnumVariable {
// success
}
또 다른 접근방식은if case
쉼표(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
}
}
제 프로젝트에서는 이렇게 썼어요.근데 어디서 그런 생각을 했는지 기억이 안 나.(방금 검색했는데 그런 용도는 보이지 않습니다.)어떤 의견이라도 주시면 감사하겠습니다.
Swift 4.1부터는 추가만 하면 됩니다.Equatable
protocol to your enum 및 useXCTAssert
또는XCTAssertEqual
:
enum SimpleToken : Equatable {
case Name(String)
case Number(Int)
}
let t1 = SimpleToken.Number(123)
let t2 = SimpleToken.Number(123)
XCTAssertEqual(t1, t2) // OK
t1과 t2는 숫자가 아니라 Simple의 인스턴스입니다.값이 관련되어 있는 토큰.
라고 말할 수 있다
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)")
}
받아들여진 답변과 비교할 때 'default'는 'main' switch 문에 'default' 대소문자가 없기 때문에 다른 대소문자와 함께 열거형을 확장하면 컴파일러는 나머지 코드를 강제로 갱신합니다.
enum SimpleToken: Equatable {
case Name(String)
case Number(Int)
}
extension SimpleToken {
func isEqual(st: SimpleToken)->Bool {
switch self {
case .Name(let v1):
switch st {
case .Name(let v2): return v1 == v2
default: return false
}
case .Number(let i1):
switch st {
case .Number(let i2): return i1 == i2
default: 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
위의 답변 외에 계산된 속성을 도우미로 추가할 수 있습니다.또한 가독성을 최적화하는 다양한 방법 중 하나입니다.
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 5에서는 Equatable 프로토콜을 사용하여 다음과 같이 Enum을 비교할 수 있습니다.
enum MyEnum: Equatable {
case firstCase(String)
case secondCase(Int)
case thirdCase(Bool)
}
let enum1 = MyEnum.firstCase("hello")
let enum2 = MyEnum.firstCase("hello")
let enum3 = MyEnum.firstCase("world")
if enum1 == enum2 {
print("enum1 and enum2 are equal")
} else {
print("enum1 and enum2 are not equal")
}
if enum1 == enum3 {
print("enum1 and enum3 are equal")
} else {
print("enum1 and enum3 are not equal")
}
출력은 다음과 같습니다.
enum1 and enum2 are equal
enum1 and enum3 are not equal
스위치를 사용하여 비교할 수 있습니다.
enum SimpleToken {
case Name(String)
case Number(Int)
}
let t1 = SimpleToken.Number(123)
let t2 = SimpleToken.Number(123)
switch(t1) {
case let .Number(a):
switch(t2) {
case let . Number(b):
if a == b
{
println("Equal")
}
default:
println("Not equal")
}
default:
println("No Match")
}
언급URL : https://stackoverflow.com/questions/24339807/how-to-test-equality-of-swift-enums-with-associated-values
'it-source' 카테고리의 다른 글
폴더가 존재하지 않는 경우 Bash를 사용하여 폴더를 작성하려면 어떻게 해야 합니까? (0) | 2023.04.21 |
---|---|
어레이가 다른 어레이의 서브셋인지 확인합니다. (0) | 2023.04.21 |
Windows에서 Git으로 작업하도록 에디터를 설정하려면 어떻게 해야 합니까? (0) | 2023.04.21 |
SELECT DISTING이 지정된 경우 ORDER BY 항목이 선택 목록에 표시되어야 합니다. (0) | 2023.04.21 |
WPF에서 DPI를 취득하려면 어떻게 해야 하나요? (0) | 2023.04.21 |