Swiftで遊ぼう! on Hatena

あしたさぬきblogでやってた初心者オヤジのiOSプログラミング奮闘記がHatenaに来ました

Swiftで遊ぼう! - 818 - Operator Overloading チュートリアル 1

以下のチュートリアをSwift 3向けに書き換えています。

www.raywenderlich.com


「オペレーター・オーバーロード」とは既存のオペレーターの機能を拡張することです。どういうことか具体的に説明していこう。

まず次のコードを直感的に考えてみます。

let pt1 = CGPoint(x: 10, y: 20)
let pt2 = CGPoint(x: -5, y: 0)
let pt3 = pt1 + pt2
let pt4 = pt3 * 100

初心者の私はpt3が(5, 20)になり、そしてpt4は(500, 2000)になると思います。

しかし、これをplaygroundに入力するとエラーが表示されます。そうなんです。Swiftの標準オペレーターにベクトル計算は備わっていないんです。ここでオペレーターを拡張する機能がオペレーター・オーバーということになります。

この機能を説明する前に知っておかなければならないことがあります。

Precidence(優先度)

学生の頃に習ったように算術オペレーターには優先度があります。

var sumWithMultiplication = 1 + 3 - 3 * 2

このオペレーションには順番があります。

  1. まず、3 * 2
  2. 次に、1 + 3
  3. 最後に、4 - 6

そして計算結果は「-2」となります。

次に算術オペレーター「+」は単に数字を加えるというだけではありません。次のようにArray型の配列を加える場合はどうなるでしょう?

var sumArray = [1, 2] + [1, 2]

Arrayの加算オペレーターで得られる値は「[1, 2, 1, 2]」なります。私が期待していた値は「[2, 4]」だったのですが、標準のままでは得られません。これを得るためにカスタムメソッドを作るとしたら次のようになります。

func add(left: [Int], right: [Int]) -> [Int] {
    var sum = [Int]()
    assert(left.count == right.count, "vector of same length only")
    for (key, _) in left.enumerated() {
        sum.append(left[key] + right[key])
    }
    return sum
}

これを使って計算すると期待している値が得られます。

var arr1 = [1, 1]
var arr2 = [1, 1]
var arr3 = add(left: arr1, right: arr2)

これで「[2, 2]」が得られます。でも毎回この関数を呼んで計算するのでなく「+」を使って同様の機能を拡張する方法がオペレーター・オーバーロードというわけです。

オペレーター・オーバーロード

オペレーター・オーバーロードを使うとStructureとClassにある既存のオペレーターに機能を加えることができます。ということで次の機能強化ができます。

func + (left: [Int], right: [Int]) -> [Int] { // 1
    var sum = [Int]() // 2
    assert(left.count == right.count, 
        "vector of same length only")  // 3
    for (key, _) in left.enumerated(){
        sum.append(left[key] + right[key]) // 4
    }
    return sum
}
  1. 普通の関数定義と同じコーディング法で、既存のオペレーター演算子を関数名に使います。
  2. 空っぽのArray型を用意します。
  3. ここでデバックで一般的なasertを使います。条件に合わなければコンソールに独自のメッセージを表示させられます。
  4. 1つづずArrayの項目を足し合わせて追加していきます。

この関数を定義したplaygroundで次のコードを加えます。

var sumArray1 = [1, 2, 3] + [1, 2, 3]

これで期待している「[2, 4 ,6]」が得られます。

今日はここまで。残りはまた後で。