Programmer's Note

コード読み書きの備忘録。

SwiftのOptional型の動作を確かめてみる

SwiftのOptional型について。
いろんなサイトで解説されているが、自分でもやってみて理解する。
ここが分かりやすい:
[Swift] Optional 型についてのまとめ Ver2 - Qiita

(1) Optioanlでない通常の変数の宣言

var a:Int

println(a)

値を代入しないと、コンパイルエラーになる↓

<stdin>:4:9: error: variable 'a' used before being initialized
println(a)
^
<stdin>:2:5: note: variable defined here
var a:Int

(2) Optional型にしてみる。

var a:Int?

println(a)

結果:

nil

結果はnil。Optional型はデフォルト値はnilになる。
つまり、Optional型にして初めて値なし、が使える。

Optional型の別の記法である以下の書き方もできる。

var a:Optional<Int>

println(a)

Int型をOptionalで包んでいる感じ。ラッピングしてる。
本家のチュートリアルでwrap、unwrapって説明しているのを最初読んだときは、
意味不明だったが、これを最初に示してくれたら一発だった。

(3) unwrap

unwrapは、! で行う。
値を代入しないまま、unwrapすると、実行時エラーになる。

var a:Optional<Int>

println(a!)

結果は略。
以下のような場合は、

var a:Optional<Int> = 1

println(a!)

結果:
1

になる。
これだけを見るとOptional型のメリットはあんましない・・・。

(4) Optional Chaining

?を使うとnilになる可能性のあるオブジェクトのプロパティに安全にアクセスできる。

以下のコードは、

struct Bird {
    var a:Int
    init(n:Int) {
        a = n
    }
    func toString()->String {
        return "\(a)"
    }
}

var bird:Bird? = Bird(n:100)

println(bird?.toString())

結果:
Optional(100)

となる。
? を使って値を取り出す場合は、Optionalにラップしてから返すという。
これは、

   a?.b?.c?...

のように鎖のようにつながって、呼び出せるようにするため。と理解した。
(Chainingはここから来ている)

しかし、プログラマーとしては直感的には、上記 bird?.toString() は文字列"100"として
帰ってくることを期待しているのだが、、、。
birdがnilかどうか自信がないときは、ちゃんと

if let str = bird?.toString() {
   println(str)
}

のように書けということか。
(Optional型の導入理由はnilのチェック忘れを防ぐ、それをコンパイラで検出できるようにする。というところにあるから。)