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)
はそうであると仮定しています。ただし、この場合、any番号と一致させます。特定のものだけではありません。
明らかにswitchステートメントを使用できますが、==
演算子を実装する目的は、この冗長な解決策を避けることでした。
switch number {
case .Number:
print("You must play a face card!")
default:
break
}
関連付けられた値を無視しながら、列挙値を関連付けられた値と比較する方法はありますか?
注:==
メソッドの大文字と小文字をcase (.Number, .Number): return true
に変更できることに気づきましたが、それは正しくtrueを返しますが、私の比較それでも、any番号(number == CardRank.Number
)ではなく、特定の番号(number == CardRank.Number(2)
; 2はダミー値)と比較されているように見えます。
編集: Etanが指摘しているように、(_)
ワイルドカードの一致を省略して、これをよりきれいに使用できます。
残念ながら、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ステートメントを実装する列挙型に追加することを検討してください。
残念ながらSwift 1.xには別の方法がないため、if case
を使用できるSwift 2のバージョンほどエレガントではないswitch
を使用する必要があります。
if case .Number = number {
//ignore the value
}
if case .Number(let x) = number {
//without ignoring
}
In Swift 4.2 Equatable
は、関連するすべての値がEquatable
に準拠している場合に合成されます。必要なのは、Equatable
を追加するだけです。
enum CardRank: Equatable {
case Number(Int)
case Jack
case Queen
case King
case Ace
}
https://developer.Apple.com/documentation/Swift/equatable?changes=_
より簡単なアプローチを次に示します。
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!")
}