Après avoir lu Comment tester l'égalité de Swift enum avec les valeurs associées , j'ai implémenté l'énumération suivante:
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
}
}
Le code suivant fonctionne:
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.")
}
Cependant, cela ne compile pas:
let number = CardRank.Number(5)
if number == CardRank.Number {
print("You must play a face card!")
}
... et le message d'erreur suivant s'affiche:
L'opérateur binaire '==' ne peut pas être appliqué aux opérandes de type 'CardRank' et '(Int) -> CardRank'
Je suppose que c'est parce qu'il attend un type complet et que CardRank.Number
Ne spécifie pas un type entier, alors que CardRank.Number(2)
l'a fait. Cependant, dans ce cas, je veux qu’il corresponde à n’importe quel numéro ; pas seulement un spécifique.
Évidemment, je peux utiliser une instruction switch, mais le but de l'implémentation de l'opérateur ==
Était d'éviter cette solution prolixe:
switch number {
case .Number:
print("You must play a face card!")
default:
break
}
Est-il possible de comparer une énumération avec des valeurs associées tout en ignorant sa valeur associée?
Remarque: Je réalise que je pourrais changer la casse de la méthode ==
En case (.Number, .Number): return true
, mais retournerait vrai correctement, ma comparaison ressemblerait toujours comme si elle était comparée à un nombre spécifique (number == CardRank.Number(2)
; où 2 est une valeur factice) plutôt que toute nombre (number == CardRank.Number
).
Edit: Comme Etan le fait remarquer, vous pouvez omettre le (_)
match générique pour utiliser ceci plus proprement.
Malheureusement, je ne pense pas qu'il existe un moyen plus facile que votre approche switch
dans Swift 1.2.
Dans Swift 2, cependant, vous pouvez utiliser le nouveau if-case
correspondance de modèle:
let number = CardRank.Number(5)
if case .Number(_) = number {
// Is a number
} else {
// Something else
}
Si vous cherchez à éviter la verbosité, vous pouvez envisager d'ajouter une propriété calculée isNumber
à votre enum qui implémente votre instruction switch.
Malheureusement, dans Swift 1.x, vous devez utiliser switch
qui n’est pas aussi élégant que Swift 2 version où vous pouvez utiliser if case
:
if case .Number = number {
//ignore the value
}
if case .Number(let x) = number {
//without ignoring
}
Dans Swift 4.2 Equatable
sera synthétisé si toutes vos valeurs associées sont conformes à Equatable
. Tout ce que vous avez à faire est d'ajouter Equatable
.
enum CardRank: Equatable {
case Number(Int)
case Jack
case Queen
case King
case Ace
}
https://developer.Apple.com/documentation/Swift/equatable?changes=_
Voici une approche plus simple:
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)
}
}
Il n'est pas nécessaire de surcharger l'opérateur == et la vérification du type de carte ne nécessite pas de syntaxe déroutante:
let card = CardRank.Jack
if card == CardRank.Jack {
print("You played a jack")
} else if !card.isFaceCard {
print("You must play a face card!")
}