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のチェック忘れを防ぐ、それをコンパイラで検出できるようにする。というところにあるから。)