この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
SwiftではC++であるような演算子のオーバーロードにも対応しています。
今回はそんな演算子のオーバーロードがswitch文にも適用出来るよという話です。
演算子のオーバーロードとは?
まずは演算子のオーバーロードについて簡単におさらいです。
演算子のオーバーロードは演算子について独自に拡張をすることが出来ます。
また、グローバル関数として定義する必要があります。
サンプル
例えば、独自定義した構造体 Card
があるとします。
このCardはトランプカードの構造体です。
struct Card {
enum Suit: Character {
case Spades = "♠", Hearts = "♡", Diamonds = "♢", Clubs = "♣"
}
enum Rank: Int {
case Ace = 1, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King
}
let rank: Rank, suit: Suit
}
Card同士を+
で足した場合エラーになります。(当たり前ですが。。。)
そこで、独自でCardを足すとカードの数字の合計値を返す演算子のオーバーロードを作ります。
func + (left: Card, right: Card) -> Int {
return left.rank.rawValue + right.rank.rawValue
}
すると、以下のコードが通るようになり、Card + Card は、カードの数字を足した結果が返ってきます。
let card1 = Card(rank: .Ace, suit: .Spades)
let card2 = Card(rank: .Seven, suit: .Hearts)
let addRank = card1 + card2
print(addRank) // 8 が表示される(Int型)
switch文の演算子オーバーロード
switch文の演算子オーバーロードには、
~=
演算子を使用します。
サンプル
上のサンプルで使ったCard構造体を再度使用します。
Cardに対して直接マーク(suit)をswitch文で書いても通常はエラーになります。
~=
を使用し、独自でCardを比較する演算子オーバーロードを作ります。
func ~= (pattern: Character, value: Card) -> Bool {
return pattern == value.suit.rawValue
}
pattern
は caseの値に対応します。
~=
のオーバーロードを作成することにより、下記のコードが通るようになります。
let card = Card(rank: .Jack, suit: .Clubs)
switch card {
case "♠": break
case "♡": break
case "♢": break
case "♣": break
default:
print("not match")
}
また、
func ~= (pattern: Int, value: Card) -> Bool {
return pattern == value.rank.rawValue
}
のように書くと、
switch card {
case 1:
print("カードは1です")
case 11:
print("カードは11です")
default:
print("カードは1と11ではありません")
}
のように書けます。(ヒドい感じの例ですが、、、)
また、func ~= (pattern: Character, value: Card) -> Bool {...}
と func ~= (pattern: Int, value: Card) -> Bool {...}
は併用して使えます。
上記の例ですと、caseにCharacterを記載した場合はマークを、Intを記載した場合はカードの数字と比較します。
さいごに
内容的には小ネタレベルの話ですが、The Swift Programming Language (Swift 2.2) の Expression Patternの部分を読んでいた時に、switch文は~=で出来るのを知ったのでメモとして記事に残しておきます。