\
2014年08月17日
Posted by 屋台ブルー at 2014年08月17日00:00 Comment(0)

Swiftで遊ぼう! - 38 サブスクリプト? 計算プロパティと何が違うの?

swift_logoさて、昨日からの続きで今日はサブスクリプトを勉強してみる。説明を読んでいくと、ここでもセッター、ゲッターって言葉が出てくる。セッター、ゲッター? あれ、どこかで出てきたような。そうそう、ここに(Swiftで遊ぼう! - 6 セッター、ゲッター、何のコッチャー)ありました。振る舞いがまったく一緒に思える。ただ「subscript」というシンタックスをつけるかつけないかの話ではないか! というか配列型や辞書型のインスタンスからエレメントを抽出する呼び出しがサブスクリプトという説明もされている! →配列型インスタンス[インデックス]とか辞書型インスタンス[キー値]でエレメント値を呼び出す方法「[]を使って」がまさにサブスクリプト!

計算値プロパティとどのように使い分けるのでしょう。まあ、もう少しちゃんとした理解が必要なので、サブスクリプトの説明をみていく。

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
}
}
}

var matrix = Matrix(rows:2, columns:2)

上記のコードをじーっと眺めて読んでいく。私は一月前までの私ではない! 少しは読めるようになってきているので、ちょっと解説をつけて説明をしよう。

1) 最初に構造型Matrixの箱作り宣言。
2) このMatrixには3つのプロパティが定義されている。Intタイプのrowsとcolumns、そしてDoubleタイプの配列型gridだ。さて、注意しなければならないのが、ここでデフォルト型の初期化は行われていない。いままでよくありがちな、「let rows:Int=0」のような宣言です。
3) デフォルトプロパティ初期化がされていないので、初期化の記述が必要になります。そこで、ここで宣言されているinit()はメンバーワイズ初期化のステップがとられている。ということは、インスタンスを宣言するときに必ず初期化パラメーターに引数を指定しないとエラーになる。また、初期化の時の引数代入にはパラメーター名を表記しなければならない。これは関数の時と挙動が違うので間違えないように。
4) おっと、次の関数indexIsValidForRowも構造体のプロパティになるのかな。後で指定されるrowとcolumnの値が範囲を超えているかどうかの判定をする関数だ。範囲内にあればtrueを返し、範囲をオーバーしていたらfalseを返すだけ。
5) そして、次に出てくるサブスクリプトがこの構造体のミソになる。実は、この構造体はrowsで指定する最大行数とcolumnsで指定された最大列数の数字と、それで構成される格子数(rows×columns)の配列型gridしか与えられていない。ということは、gridの順番は一直線上と考えていいだろう。それを擬似的に格子状に扱って、アクセスする方法をサブスクリプトの形で実現していることになる。
というのもgridというのは配列なんで、以下のようにエレメント値にアクセスすることができる。
matrix.grid[1] = 3.0
すると、gridの配列は[0.0,3.0,0.0,0.0]
こうなるが、こんなやり方をすれば思惑が外れて意味がないよね。
6) そこで格子状にエレメントにアクセスするサブスクリプトがgetで定義されている。その前のassertはデバック作業なんで範囲外の数字を入力するとプログラムが中断してエラーメッセージを返す。範囲内なら、格子状の指定[x,y]を直線上の配列インデックスに一致させる計算式「row×columns]+column」で指定された配列のエレメント値をDouble型で返す。
7) 新しく配列エレメント値を変更したいときは、setで定義されているように指定された配列に新しいnewValue「←指定がなければデフォルトです。これは計算型プロパティと同じだよね。」が組み込まれる。

と、こんな風に説明できるのでしょう。おお、なんか少し理解できているじゃないですか私。今日はこの辺にしとこう。では。


同じカテゴリー(Swiftで遊ぼう!)の記事画像
Swiftで遊ぼう! - プログラミングまとめ(ときどき更新)
Swiftで遊ぼう! - 番外編 - Xcode6:ショートカットと用語説明
Swiftで遊ぼう! - 209 - ルートビューのコードは続く:CGRect
Swiftで遊ぼう! - 208 - ルートビューのコード
Swiftで遊ぼう! - 207 - ツールバーボタンとビューコントローラーを繋ぐ
Swiftで遊ぼう! - 206 - ビューコントローラーにビューコントローラーを載せる
同じカテゴリー(Swiftで遊ぼう!)の記事
 Swiftで遊ぼう! - プログラミングまとめ(ときどき更新) (2021-01-31 00:00)
 Swiftで遊ぼう! - 番外編 - Xcode6:ショートカットと用語説明 (2015-04-05 00:00)
 Swiftで遊ぼう! - 209 - ルートビューのコードは続く:CGRect (2015-02-06 00:00)
 Swiftで遊ぼう! - 208 - ルートビューのコード (2015-02-05 00:00)
 Swiftで遊ぼう! - 207 - ツールバーボタンとビューコントローラーを繋ぐ (2015-02-04 00:00)
 Swiftで遊ぼう! - 206 - ビューコントローラーにビューコントローラーを載せる (2015-02-03 00:00)

上の画像に書かれている文字を入力して下さい
 
<ご注意>
書き込まれた内容は公開され、ブログの持ち主だけが削除できます。

削除
Swiftで遊ぼう! - 38 サブスクリプト? 計算プロパティと何が違うの?
    コメント(0)