Swiftの変数&定数が、自動的にlazyとして扱われる条件を調べた時のメモ
変数や定数の宣言時にlazyを付けてなくても自動的に遅延評価される場合があるので、その条件を調べた時のメモです。
動作を確認した環境
環境 | 情報 |
---|---|
Xcode | 6.1.1 (6A2008a) |
iOS | 8.1 |
Swift | 1.1 |
Date | 2015/3/9 |
ソースコード
テストに使ったソースコードはこんな感じ。
import UIKit // テスト用クラス class LazyTest { let name: String init(name: String) { self.name = name println("init: \(name)") } deinit { println("deinit: \(name)") } } // グローバル変数(※letで宣言) let g_lazy0 = LazyTest(name: "g_lazy0 - let global") class ViewController: UIViewController { // 通常のプロパティ(※letで宣言) let lazy1 = LazyTest(name: "lazy1 - let") // lazyプロパティ lazy var lazy2 = LazyTest(name: "lazy2 - lazy var") struct Const { // 構造体定数 static let lazy3 = LazyTest(name: "lazy3 - static let(struct)") } func testLazy() { // ローカル変数 let lazy4 = LazyTest(name: "lazy4 - let local") // それぞれの変数にアクセス println(" [1] g_lazy0: \(g_lazy0.name)") println(" [2] lazy1: \(lazy1.name)") println(" [3] lazy2: \(lazy2.name)") println(" [4] Const.lazy3: \(Const.lazy3.name)") println(" [5] lazy4: \(lazy4.name)") } override func viewDidLoad() { super.viewDidLoad() testLazy() } }
実行結果
コードを実行した結果はこんな感じ。
init: lazy1 - let init: lazy4 - let local init: g_lazy0 - let global [1] g_lazy0: g_lazy0 - let global [2] lazy1: lazy1 - let init: lazy2 - lazy var [3] lazy2: lazy2 - lazy var init: lazy3 - static let(struct) [4] Const.lazy3: lazy3 - static let(struct) [5] lazy4: lazy4 - let local deinit: lazy4 - let local
この結果から読み取れる情報はこんな感じ。
- lazy1はViewControllerの通常のプロパティで、ViewControllerが生成されるタイミングで同時に生成されている
- lazy4はtestLazy()の中で定義されているローカル変数で、定義と同時に普通に生成されている
- g_lazy0は普通のグローバル変数(lazy宣言していない)だが、最初にアクセスしたタイミングで生成されている
- lazy2はViewControllerの通常のプロパティだが、lazyで宣言してあるので、最初にアクセスしたタイミングで生成されている
- lazy3は普通の構造体定数(lazy宣言していない)だが、最初にアクセスしたタイミングで生成されている
まとめ
- グローバル変数は自動的にlazyになる
- 構造体定数も自動的にlazyになる
- lazyはvarにしか使えないはずだが、自動でlazyになる場合はletでもなる
グローバル変数が自動的にlazyになる件は、どっかの資料で見たんだけど・・・ どこで見たか、思い出せない。
structのstatic letがlazyになるのは、そうだろうと思って試してみたら、本当にそうなってた。Swiftは面白いな。
Swift 1.2では構造体と同じようにクラスも定数を持てるようになるらしいけど、同じような動作になるんじゃないかな? たぶん。