【Swift】レイジープロパティ(lazy)の使い方。最初にアクセスされたときに初期値が決まる。(Swift 2.1、XCode 7.2)
レイジープロパティとは
レイジープロパティ(lazy stored property)とは、参照されるときに初めて初期値が設定されるプロパティのことである。
レイジープロパティは以下のように定義する。インスタンス生成後に値を変更するプロパティなので定数(let)で宣言することはできない。
1 2 3 4 |
class クラス名 { lazy var プロパティ名 = 変数またはメソッド } |
以下のコードは、普通のプロパティを利用する例。商品クラスに含まれる価格(price)は外部変数のディーラー価格(dealer_price)の値で初期化する。
商品クラスのインスタンスを作ったあとにディーラー価格を7000円に変更し、商品クラスのインスタンスの価格を参照すると5000円と表示される。つまり、インスタンスが生成されたときにディーラー価格を参照して価格が決定されるということだ。
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 |
/* ** 通常のプロパティを参照する例 */ var dealer_price = 5000 //商品クラス class Shouhin { var price: Int = dealer_price } //商品クラスのインスタンスを利用 var test = Shouhin() //ディーラー価格を変更 dealer_price = 7000 print(test.price) //再度ディーラー価格を変更 dealer_price = 9000 print(test.price) //実行結果 //5000 //5000 |
一方、以下のコードは価格のプロパティをレイジープロパティに変更したものである。先ほどと同じように、商品クラスのインスタンスを作ったあとにディーラー価格を7000円に変更し、商品クラスのインスタンスの価格を参照すると、今度は7000円が表示される。
これが意味するのは、インスタンスを生成したときはまだ初期値が定まってなくて、価格を初めて参照したときに初期値が設定されているということだ。このように、レイジープロパティはプロパティが必要になったときに初めて値を設定したいときに使える機能である。
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 |
/* ** レイジープロパティを参照する例 */ var dealer_price = 5000 //商品クラス class Shouhin { lazy var price: Int = dealer_price } //商品クラスのインスタンスを利用 var test = Shouhin() //ディーラー価格を変更 dealer_price = 7000 print(test.price) //再度ディーラー価格を変更 dealer_price = 9000 print(test.price) //実行結果 //7000 //7000 |
メソッドを使って初期化する
レイジープロパティに代入する値は、変数に限らず、メソッドを呼び出して値を設定することができる。以下のコードは、自身のメソッドを呼び出してレイジープロパティの初期化を行う例である。計算結果を初期値に設定するのに使える。
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 |
/* ** メドッド呼び出しでレイジープロパティを設定する例 */ var dealer_price = 5000 //商品クラス class Shouhin { lazy var price: Int = self.calcPrice() func calcPrice() -> Int { return dealer_price * 2 } } //商品クラスのインスタンスを利用 var test = Shouhin() //ディーラー価格を変更 dealer_price = 7000 print(test.price) //実行結果 //14000 |
なお、通常のプロパティは値にメソッドを記述することはできない。インスタンス生成されてないインスタンスメソッドを使うことができなイメージ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/* ** 通常のプロパティはメソッドで値を初期化することはできない */ var dealer_price = 5000 //商品クラス class Shouhin { var price: Int = self.calcPrice() func calcPrice() -> Int { return dealer_price * 2 } } //コンパイルエラー //error: use of unresolved identifier 'self' |
クロージャを使って初期化する
以下のコードのように、クロージャを使ってレイジープロパティを設定することもできる。レイジープロパティのためだけのメソッドならば、このようにクロージャにしてしまったほうがコードがスッキリして良い。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/* ** クロージャを使ってレイジープロパティの値を初期化する */ var dealer_price = 5000 //商品クラス class Shouhin { lazy var price:Int = { dealer_price * 2 }() } //商品クラスのインスタンスを利用 var test = Shouhin() //ディーラー価格を変更 dealer_price = 7000 print(test.price) //実行結果 //14000 |
なお、クロージャは変数として扱われるものなので通常のプロパティを初期化するときにも使える。初期化されるタイミングは変数を代入するときと同じである。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/* ** クロージャを使って通常のプロパティを初期化する */ var dealer_price = 5000 //商品クラス class Shouhin { var price:Int = { dealer_price * 2 }() } //商品クラスのインスタンスを利用 var test = Shouhin() //ディーラー価格を変更 dealer_price = 7000 print(test.price) //実行結果 //10000 |