Swift에서 관련 값을 무시하여 enum을 관련 값과 비교하는 방법은 무엇입니까?


87

How to test equality of Swift enums with associated values를 읽은 후 다음 enum을 구현했습니다.

enum CardRank {
    case Number(Int)
    case Jack
    case Queen
    case King
    case Ace
}

func ==(a: CardRank, b: CardRank) -> Bool {
    switch (a, b) {
    case (.Number(let a), .Number(let b))   where a == b: return true
    case (.Jack, .Jack): return true
    case (.Queen, .Queen): return true
    case (.King, .King): return true
    case (.Ace, .Ace): return true
    default: return false
    }
}

다음 코드가 작동합니다.

let card: CardRank = CardRank.Jack
if card == CardRank.Jack {
    print("You played a jack!")
} else if card == CardRank.Number(2) {
    print("A two cannot be played at this time.")
}

그러나 이것은 컴파일되지 않습니다.

let number = CardRank.Number(5)
if number == CardRank.Number {
    print("You must play a face card!")
}

... 다음과 같은 오류 메시지가 표시됩니다.

이항 연산자 '=='는 'CardRank'및 '(Int)-> CardRank'유형의 피연산자에 적용 할 수 없습니다.

나는 이것이 전체 유형을 기대하고 전체 유형을 CardRank.Number지정하지 않았기 때문에 이것이라고 가정하고 CardRank.Number(2)있습니다. 그러나이 경우 어떤 숫자 와 일치하기를 원합니다 . 특정한 것이 아닙니다.

분명히 switch 문을 사용할 수 있지만 ==연산자 구현의 요점은 이 장황한 솔루션을 피하는 것이 었습니다.

switch number {
case .Number:
    print("You must play a face card!")
default:
    break
}

연관된 값을 무시하면서 열거 형을 연관된 값과 비교할 수있는 방법이 있습니까?

참고 : 나는 내가 경우를 바꿀 수 실현 ==에 대한 방법 case (.Number, .Number): return true(제대로 사실 반환하지만,하지만, 내 비교는 여전히 특정 번호에 비해 그 존재처럼 보이는 것 number == CardRank.Number(2), (2)는 더미 값이다)보다는 어떤 수를 ( number == CardRank.Number).


1
당신은 줄일 수 있습니다 Jack, Queen, King, Ace의 사례를 ==단지에 연산자 구현 :case (let x, let y) where x == y: return true
알렉산더 - 분석 재개 모니카

답변:


72

편집 : Etan이 지적했듯이 (_)와일드 카드 일치를 생략하여 보다 깔끔하게 사용할 수 있습니다 .


안타깝게도 switchSwift 1.2에서 접근 하는 것보다 쉬운 방법은 없다고 생각합니다 .

그러나 Swift 2에서는 새로운 if-case패턴 일치를 사용할 수 있습니다 .

let number = CardRank.Number(5)
if case .Number(_) = number {
    // Is a number
} else {
    // Something else
}

자세한 정보를 피하려면 isNumberswitch 문을 구현하는 열거 형에 계산 된 속성을 추가하는 것을 고려할 수 있습니다 .


1
이것은 제어 흐름에 적합하지만 간단한 표현을 원할 때는 약간 짜증이납니다 assert(number == .Number). 예 : . 나는 이것이 이후 버전의 Swift에서 개선되기를 바랄뿐입니다. = /
제레미

3
while 루프 조건 등과 같은 것도 짜증납니다. Swift 3에서는 더 깨끗한 코드를 위해 (_)를 제거 할 수 있습니다.
에탄

@Etan에게 감사드립니다. 답변에 추가했습니다. 실제로 Swift 2에서도 와일드 카드를 생략 할 수 있습니다. 이 답변은 언어 기능이 출시되기 전에 작성되었으므로 아직 몰랐습니다! :-D
Ronald Martin

또한 : 열거 형에 연관된 값이있는 단일 케이스가있는 경우 연관된 값이없는 케이스에도 if-case 패턴을 사용해야합니다.
ETAN

1
@PeterWarbo,이 패턴 일치 구문으로 부정을 할 수 없습니다. 지금은 defaultswitch블록 의 케이스로 돌아 가야합니다 .
로널드 마틴

28

불행히도 Swift 1.x에는 다른 방법이 없으므로 사용해야합니다. switch 있는 Swift 2 버전만큼 우아하지 않은 합니다 if case.

if case .Number = number {
    //ignore the value
}
if case .Number(let x) = number {
    //without ignoring
}

3
슬프게도 이것은 if표현이 아닌 진술 에서만 작동 합니다.
Raphael


3

다음은 더 간단한 접근 방식입니다.

enum CardRank {
    case Two
    case Three
    case Four
    case Five
    case Six
    case Seven
    case Eight
    case Nine
    case Ten
    case Jack
    case Queen
    case King
    case Ace

    var isFaceCard: Bool {
        return (self == Jack) || (self == Queen) || (self == King)
    }
}

== 연산자를 오버로드 할 필요가 없으며 카드 유형을 확인하는 데 복잡한 구문이 필요하지 않습니다.

let card = CardRank.Jack

if card == CardRank.Jack {
    print("You played a jack")
} else if !card.isFaceCard {
    print("You must play a face card!")
}

3
중요한 질문에 대한 답은 아니지만 IMO는 OP와 유사한 시나리오에서 더 우아한 솔루션 (열거 된 숫자 제외)이며, 반대표를 받아서는 안됩니다.
Nathan Hosselton

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.