Прочитав Как проверить равенство перечислений 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
}
Is there any way to compare an enum with associated values while ignoring its associated value?
Note: I realize that I could change the case in the ==
method to case (.Number, .Number): return true
, but, although it would return true correctly, my comparison would still look like its being compared to a specific number (number == CardRank.Number(2)
; where 2 is a dummy value) rather than any number (number == CardRank.Number
).
источник
Jack
,Queen
,King
,Ace
cases in the==
operator implementation to just:case (let x, let y) where x == y: return true
Ответы:
Edit: As Etan points out, you can omit the
(_)
wildcard match to use this more cleanly.Unfortunately, I don't believe that there's an easier way than your
switch
approach in Swift 1.2.In Swift 2, however, you can use the new
if-case
pattern match:let number = CardRank.Number(5) if case .Number(_) = number { // Is a number } else { // Something else }
If you're looking to avoid verbosity, you might consider adding an
isNumber
computed property to your enum that implements your switch statement.источник
assert(number == .Number)
. I can only hope this is improved in later versions of Swift. =/default
case in aswitch
block for now.Unfortunately in Swift 1.x there isn't another way so you have to use
switch
which isn't as elegant as Swift 2's version where you can useif case
:if case .Number = number { //ignore the value } if case .Number(let x) = number { //without ignoring }
источник
if
statements, not as an expression.In Swift 4.2
Equatable
will be synthesized if all your associated values conform toEquatable
. All you need to do is addEquatable
.enum CardRank: Equatable { case Number(Int) case Jack case Queen case King case Ace }
https://developer.apple.com/documentation/swift/equatable?changes=_3
источник
Here's a simpler approach:
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) } }
There's no need to overload the == operator, and checking for card type does not require confusing syntax:
let card = CardRank.Jack if card == CardRank.Jack { print("You played a jack") } else if !card.isFaceCard { print("You must play a face card!") }
источник
You don't need
func ==
orEquatable
. Just use an enumeration case pattern.let rank = CardRank.Ace if case .Ace = rank { print("Snoopy") }
источник