オプショナル型について(Swift)

今回はSwiftのオプショナル型について書いていきたいと思います!

オプショナル型とは

Swiftにはオプショナル型と非オプショナル型があります。
大きな違いはnilの代入が可能がどうかです!
オプショナル型はnilの代入が可能
非オプショナル型はnilの代入が不可能
となっています。
普通に変数宣言した場合は非オプショナル型になります。


オプショナル型の宣言方法

オプショナル型の宣言には「?」か「!」のどちらかを使います。
例を以下に示します。

var ho:Int?

もしくは

var ge:Int!

ここでは「?」も「!」もオプショナル型なのですが、
「!」は自動でForced Unwrapping をやります。
Forced Unwrappingについては下の方で説明しています。
通常の変数宣言だと初期値を必ずいれないといけませんが、
オプショナル型では初期値を代入しなくとも宣言ができます。
初期値を代入しない場合は「nil」が入ります。
以下の例で確認してみましょう

var hoge:String?
println(hoge)
//出力 => nil
hoge = "hello"
println(hoge)
//出力 => Optional("hello")

上記のコードで宣言時の「?」を消すとエラーがでると思います。
これは非オプショナル型になり初期値に「nil」を自動で代入できなくなったためです。
またここで2回目の出力が「hello」ではなく「Optional("hello")」だということを頭の隅においといてください。

アンラップとは

オプショナル型の変数は通常の変数と同じように使用ができません。
例えば以下のコードはエラーになると思います。

var ho:Int? = 10
var ge:Int = 20
ho+ge

これはオプショナル型と非オプショナル型は同じように扱い得ないということです。
ここで少し上でやった出力が「Optional("hello")」になるということがありましたね!
この出力はオプショナル型と非オプショナル型の違いを表しています。
そこで同じように扱うためにオプショナル型をアンラップし、中身の値だけを取り出します。

アンラップの種類

代表的なアンラップの種類は以下のものがあります。

  • Forced Unwrapping (強制的アンラップ)
  • Optional Binding (オプショナルバインディング)
  • Optional Chaining (オプショナルチェイニング)

それぞれについて以下で簡単に説明します。

Forced Unwrapping (強制的アンラップ)

このアンラップ方法は名前の通りどんな値が入っていても強制的にアンラップを行います。
そのため、「nil」がはいっている変数をアンラップしようとするとエラーによりアプリケーションが落ちてしまうため注意が必要です。
Forced Unwrapping の記述方法はオプショナル変数の最後に「!」をつけるだけです。
例を以下に示します。

var ho:Int? = 10
var ge:Int = 20
ho!+ge
//!をとるとアンラップしてないためのエラーがでます

とても簡単で便利ですが「nil」が入ることがある変数に対しては注意して使う必要があります。

Optional Binding (オプショナルバインディング)

このアンラップ方法はifなどの条件式と組み合わせて使います。
Forced Unwrappingの方ほとは違いこの方法は「nil」が入っていてもエラーは発生しません。
Optional Bindingの記述方法は

if var 変数名 = オプショナル型の変数 { 処理 }

です。
もし「nil」でなければオプショナル型の中身だけを変数にいれ処理を実行します。
ちなみに受け取る方はvarでもletでもどちらでも大丈夫です。
例を以下に示します。

var str1:String? = "Hello"
//= "Hello"を消すと結果が変わると思います。
if var str2 = str1{
        println(str2)
}else{
        println("nilです")
}

このようにOptional Binding では中身がnilかどうかを判定します。

Optional Chaining (オプショナルチェイニング)

このアンラップ方法はオプショナル型の変数のプロパティを取得したり、メソッドを呼び出すときに使います。
また、クラスのプロパティ自体がオプショナル型のときも使用します。
Optional Bindingの記述方法はオプショナル変数の最後に「?」をつけるだけです。
例を以下に示します。

class Car {
    var door:Door?
}
class Door{
    var num = 4
}

var car=Car()
let num = car.door?.num
//ここの?を抜くとエラーになります

上の例ではDoorがnilになっているので「?」をつけずに実行するとnilの先のnumを確認しようとするためエラーが起きます。
ここで「?」をつけることでDoorがnilであることを確認したらnumまで確認しにいかずにnilを返します。

おわりに

この記事はほぼサーバなどを触ったことがない人物が学んだことを整理するために書いていますので間違いなどが多々あると思います。間違いなどありましたら是非コメントなどで教えていただけると幸いです。