[iOS][Swift] switch文でも使える演算子のオーバーロード
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文は~=で出来るのを知ったのでメモとして記事に残しておきます。