16260

[code]

    class Hoge {
        var a: Int
    
        init(a: Int) {
            self.a = a // (1)
        }
    
        var b: Int {
            return self.a // (2)
        }
    
        func c() -> Int {
            return self.a // (3)
        }
    
        var d = { self.a * 2 }()  // (4)
    }
    
[/code]

上記コードで、(1),(2),(3)のselfは正しく自分を参照しますが、(4)は以下エラーが表示されます。

[code]

    <stdin>:17:19: error: use of unresolved identifier 'self'
    var d = { self.a * 2 }() // (4)
    ^
    
[/code]

また、selfを外し、

[code]

    var d = { a * 2 }()  // (4)
    
[/code]

とすると、以下エラーが表示されます。

[code]

    <stdin>:17:19: error: 'Hoge.Type' does not have a member named 'a'
    var d = { a * 2 }() // (4)
    ^
    
[/code]

実行環境は、以下になるのですが、この環境のバグでしょうか？  
それとも、何か間違っているのでしょうか？

<http://swiftstub.com/>

よろしくお願いします。


CC BY-SA 3.0
2015-09-04T06:57:08.810
16236
2015-09-04T13:42:27.770
question
swift
selfの参照について


Swiftの言語仕様上、参照型の`self`へアクセスできるタイミングは決まっているためだと思います。

> **Safety check 4**  
>  An initializer cannot call any instance methods, read the values of any
> instance properties, or refer to self as a value until after the first phase
> of initialization is complete.
>
> [Initialization - The Swift Programming
> Language](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html)

初期化処理の第一段階が完了するまでは、`self`は無効な識別子です。これはベースクラスのプロパティが初期化されていない、不定状態のインスタンスへアクセスする可能性を防ぐためです。

* * *

また、その記述が合法だとすると、別な問題がありえます。

クロージャが参照型であり、プロパティはARCによるメモリ管理がされることを考えると、`self`とクロージャは互いに強参照し、循環参照となり、一度生成したインスタンスは絶対に解放されないことになります。

この問題は遅延初期化プロパティにしていても変わらないため、

[code]

    lazy var d :() -> Int = {
        [unowned self] in
        self.a * 2
    }
    
[/code]

と書くのが望ましいです。


CC BY-SA 3.0
2015-09-04T13:42:27.770
16260
2015-09-04T13:42:27.770
5337
16236
answer