Как сравнить перечисление со связанными значениями, игнорируя его связанное значение в 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
).
Ответы
Ответ 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!")
}