Menu

Category

Archive

logo


The Swift Programming Language ~ Subscripts

2014-06-18 22:00:00 +0900
  • このエントリーをはてなブックマークに追加

iBooks にある “The Swift Programming Language” の勉強メモ。Objective-C と C を普段書いている自分から、ちょっと馴染みがないものを特にまとめておきます。目次は こちら

今回は、Subscripts に関して。

Subscripts

Subscripts は、配列や Dictionary といったデータ構造に対して、そのデータにアクセスするための記述方法です。Dictionary であれば、dict[“Kazuya”] のようなものです。実際に、Swift の Dictionary はこの方法で実装されているようです。Swift では、この Subscripts をクラス・構造体・Enumeration に対して定義することもできます。

1. Subscripts Syntax

あるタイプに新しく Subscripts を定義するには、subscript キーワードを使用します。そして、インスタンスメソッドのように、引数と返り値を指定します。読み込み専用か読み書き可能の Subscripts を定義することができます。

1
2
3
4
5
6
7
8
subscript(index: Int) -> Int {
    get {
        // return an appropriate subscript value here
    }
    set(newValue) {
        // perform a suitable setting action here
    }
}

読み込み専用の Subscripts を定義する場合には、get を省略できます。このコードは、Subscripts の引数として Int を取り、それと構造体のプロパティの掛け算の結果を返す読み込み専用の Subscripts です。

1
2
3
4
5
6
7
8
9
struct TimesTable {
    let multiplier: Int
    subscript(index: Int) -> Int {
        return multiplier * index
    }
}
let threeTimesTable = TimesTable(multiplier: 3)
println("six times three is \(threeTimesTable[6])")
// prints "six times three is 18

2. More Subscripts

Subscripts は、いくつでも引数を取ることができます。また、これらの引数はどんなデータ型でも大丈夫です。また、どんなデータ型でも返り値になれます。さらに、可変引数の Subscripts も定義できます。しかし、in-out 引数は使えませんし、引数にデフォルト値を持たせることもできません。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
struct Matrix {
    let rows: Int, columns: Int
    var grid: Double[]
    init(rows: Int, columns: Int) {
        self.rows = rows
        self.columns = columns
        grid = Array(count: rows * columns, repeatedValue: 0.0)
    }
    func indexIsValidForRow(row: Int, column: Int) -> Bool {
        return row >= 0 && row < rows && column >= 0 && column < columns
    }
    subscript(row: Int, column: Int) -> Double {
        get {
            assert(indexIsValidForRow(row, column: column), "Index out of range")
            return grid[(row * columns) + column]
        }
        set {
            assert(indexIsValidForRow(row, column: column), "Index out of range")
            grid[(row * columns) + column] = newValue
        }
    }
}

// Usage
var matrix = Matrix(rows: 2, columns: 2)
matrix[0, 1] = 1.5
matrix[1, 0] = 3.2
let someValue = matrix[2, 2]
// this triggers an assert, because [2, 2] is outside of the matrix bounds

この Matrix 構造体の例では、引数を 2 つ取る Subscripts を使い、Matrix の要素のゲッターセッターを実装しています。