Подтвердить что ты не робот

Как сравнить перечисление со связанными значениями, игнорируя его связанное значение в Swift?

После чтения Как проверить равенство перечислений Swift со связанными значениями, я выполнил следующее перечисление:

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, но, хотя он вернет true правильно, мое сравнение будет по-прежнему выглядеть как его сравнение с определенное число (number == CardRank.Number(2), где 2 - фиктивное значение), а не любое число (number == CardRank.Number).

4b9b3361

Ответ 1

Изменить: Как указывает Этан, вы можете опустить подстановочное соответствие (_), чтобы использовать это более чисто.


К сожалению, я не считаю, что в Swift 1.2 есть более простой способ, чем ваш подход switch.

В Swift 2, однако, вы можете использовать новое соответствие шаблона if-case:

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

Если вы хотите избежать многословия, вы можете подумать о добавлении вычисленного свойства isNumber к вашему перечислению, которое реализует ваш оператор switch.

Ответ 2

К сожалению, в Swift 1.x нет другого способа, поэтому вам нужно использовать switch, который не такой элегантный, как версия Swift 2, где вы можете использовать if case:

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

Ответ 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!")
}