【Swift】Computedプロパティ(計算プロパティ)の使い方。(Swift 2.1、XCode 7.2)
Computedプロパティとは
Computedプロパティ(計算プロパティ)とは、関数を通してクラスのプロパティを取得、設定する機能のことをいい、以下のように定義する。
1 2 3 4 5 6 7 8 9 |
var 変数名;型 { get { 処理 return 値 } set(引数名) { 処理 } } |
普段使うプロパティはStoredプロパティ(格納プロパティ)と呼ばれ、プロパティの値を取得、設定するときは以下のコードのように「インスタンス名.プロパティ名」でアクセスし、値は直接設定される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/* ** Storedプロパティの記述例 */ class TestClass { //Storedプロパティ var name:String = "田中" let level:Int = 3 var score:Int = 1000 } //TestClassインスタンスを生成しscoreの値を変更する。 var test = TestClass() test.score = 2000 print("\(test.name)さんのスコアは\(test.score)点です。") //実行結果 //田中さんのスコアは2000点です。 |
一方、Computedプロパティを使うと、「インスタンス名.プロパティ名」でアクセスしたときに、値を取得するときはgetメソッド、値を設定するときはsetメソッドが自動で呼び出される。
例えば、以下はゲームの成績を記録するクラスの例で、打撃回数(hit_number)がComputedプロパティになる。
インスタンスを使う側は「インスタンス名.hit_number」のようにアクセスするので、打撃回数そのものにアクセスしているかのように感じるが、実際は、getメソッド、または、setメソッドを処理した結果が取得、計算されている。
このようにComputedプロパティは、他のプロパティの値をもとに算出できてしまう場合や、プロパティにアクセスする直前に何かしらのチェックや計算が必要な場合に利用できる。
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 30 31 32 33 |
/* ** Computedプロパティの例 */ //ゲーム成績クラス class GameResultClass { let level:Int = 3 //ゲーム難易度 var score:Int = 0 //得点 //打撃回数 var hit_number:Int { get { //得点÷ゲーム難易度を返す。 return score / level } set(hit_number) { //打撃回数×ゲーム難易度を得点に設定する。 score = hit_number * level } } } //ゲーム成績インスタンスに打撃回数を設定する。 var result = GameResultClass() result.hit_number = 150 print("打撃回数は\(result.hit_number)回です。") //実行結果 //打撃回数は150回です。 |
引数やメソッドを省略する
setメソッドに定義した引数名は、名前にこだわりが無ければ省略できる。省略した場合はnewValueという引数名になる。プロパティ名や引数名など似たような名前を定義すると紛らわしいので、setメソッドの引数名は常に省略したほうがスッキリして良い。
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 30 31 32 33 |
/* ** setメソッドの引数を省略する。 */ //ゲーム成績クラス class GameResultClass { let level:Int = 3 //ゲーム難易度 var score:Int = 0 //得点 //打撃回数 var hit_number:Int { get { //得点÷ゲーム難易度を返す。 return score / level } set { //打撃回数×ゲーム難易度を得点に設定する。 score = newValue * level } } } //ゲーム成績インスタンスに打撃回数を設定する。 var result = GameResultClass() result.hit_number = 150 print("打撃回数は\(result.hit_number)回です。") //実行結果 //打撃回数は150回です。 |
以下のコードのように、setメソッド自体を省略することもできる。省略すると打撃回数(hit_number)の値を設定することができなくなり、取得専用のプロパティになる。
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 |
/* ** setメソッドを省略する。 */ //ゲーム成績クラス class GameResultClass { let level:Int = 3 //ゲーム難易度 var score:Int = 1000 //得点 //打撃回数 var hit_number:Int { get { //得点÷ゲーム難易度を返す。 return score / level } } } //ゲーム成績インスタンスに打撃回数を設定する。 var result = GameResultClass() print("打撃回数は\(result.hit_number)回です。") //実行結果 //打撃回数は333回です。 |
もし、setメソッドを省略したComputedプロパティに値を設定しようとするとコンパイルエラーになる。
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 |
/* ** setメソッドのないComputedプロパティに値を設定しようとしてエラー */ //ゲーム成績クラス class GameResultClass { let level:Int = 3 //ゲーム難易度 var score:Int = 1000 //得点 //打撃回数 var hit_number:Int { get { //得点÷ゲーム難易度を返す。 return score / level } } } //ゲーム成績インスタンスに打撃回数を設定する。 var result = GameResultClass() result.hit_number = 150 //コンパイルエラー //error: cannot assign to property: 'hit_number' is a get-only property |
また、getのみのComputedプロパティにしたからといって、以下のコードのようにプロパティをlet(定数)で宣言することはできない。なぜなら、setメソッドが無くなってプロパティの値を変更できなくなったが、getメソッド内の処理によってはいつも同じ値が取得されるとは限らないので「定数では無い」ということである。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/* ** Computedプロパティは定数(let)で定義することはできない。 */ //ゲーム成績クラス class GameResultClass { let level:Int = 3 //ゲーム難易度 var score:Int = 1000 //得点 //打撃回数 let hit_number:Int { get { //得点÷ゲーム難易度を返す。 return score / level } } } //コンパイルエラー //'let' declarations cannot be computed properties |