2077
1784

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

どこよりも分かりやすいSwiftの"?"と"!"

Last updated at Posted at 2015-07-07

swiftはオプショナルが便利!

と、swiftがリリースされてから言われてますがswift初心者からすると厄介極まりないです。

?と!の使い分けが分からずとりあえず"?"をつける、ソースコードを書いていたら急にXcodeに怒られ、エラーに導かれるままに"!"をつける...

こんな経験がある方がいるのではないでしょうか。

この記事はそんなオプショナルがフワフワした状態を脱却することを目的としています。
(そのため、あまり深い部分は扱いません...)
細かく項目を区切っているため多く見えますが、サクサク読めるはずです。頑張って読んでいただければオプショナル型を理解できると約束します。
時間のない人はまとめだけ見ていただければと思います。



◼︎ 読了時間

  • オプショナル型と非オプショナル型 (4分)
    オプショナル型と非オプショナル型の違いを示します

  • オプショナル型 (6分)
    オプショナル型"?"と"!"の違い、オプショナル型のアンラップの方法についての説明です


オプショナル型と非オプショナル型

まず、オプショナル型が何なのか理解しましょう。オプショナル型とオプショナルでない型(非オプショナル型)の違いが分かればオプショナル型の大枠は掴めたも同然です。

この違いは非常に簡単です。
オプショナル型とは変数にnilの代入を許容するデータ型で、反対に非オプショナル型はnilを代入できません。オプショナル型の変数にはデータ型の最後に「?」か「!」をつけます。

詳しく見ていきましょう。

オプショナル型はデータ型

まず、オプショナル型とはデータ型の一つです。すなわち、変数の宣言時に使用します。

optional型
var age: Int? 
var name: String!

上の例では変数agenameをオプショナル型というデータ型で宣言しています。(オプショナル型の宣言方法は次の項目で説明します)



◼︎ ポイント
オプショナル型とは変数の宣言で使うデータ型の一つ。



オプショナル型とは

では、このオプショナル型とは普通のデータ型と何が違うのでしょうか。

オプショナル型の特徴は変数にnilの代入を許すとことです。逆に非オプショナル型はnilの代入を許しません。

nilとはデータが無い、変数が空の状態を表します。

iOSではnilに対して操作することでアプリケーションが落ちてしまうことがありました。そのような問題を解決するためにswiftではnilを基本的には許容しません。しかし、オプショナル型を使うことでnilを扱うことができるようになります。



◼︎ ポイント
オプショナル型で変数を宣言すると、その変数にはnilを代入することができるようになる。



オプショナル型の使い方

具体的なオプショナル型の使い方を見ていきましょう。変数をオプショナル型として宣言するにはデータ型の最後に"?"か"!"をつけます。
※ "?"と"!"の違いは後述します。両方オプショナル型なので今は同じものと思っておいてください。

オプショナル型の宣言
var hoge: String?
var fuga: Int!

上の例では両方ともオプショナル型の変数です。

反対に非オプショナル型の変数はデータ型の最後には何もつけません。

非オプショナル型の宣言
var piyo: String

この場合、変数piyoは非オプショナル型であるためnilを代入することはできません。



◼︎ ポイント
オプショナル型で変数を宣言するときにはデータ型の最後に"?"か"!"をつける。非オプショナル型は反対に何もつけない。



"!"もオプショナル

"!"はオプショナルではない、nilを許さないというのは間違いです。このことも勘違いしている人が多いかもしれません。

変数の宣言で型に!をつける場合、その変数はオプショナル型になります。

つまり、以下の2つの変数は両方ともオプショナル型ということです。

オプショナル型の宣言
var hoge: String?
var fuga: Int!


◼︎ ポイント
変数の宣言時にデータ型の最後に"!"をつけるとオプショナル型となる。



オプショナル型以外の"?"と"!"

Swiftでは、オプショナル型以外でも"?"と"!"を使う場合があります。
変数の宣言のとき以外に使う"?"や"!"はオプショナル型とは別物です。

swiftを学んだことのある方は以下のような"?"や"!"の使い方を見たことがある人もいると思います。これらの使い方はオプショナル型とは別物です。

optional型とは違う"?"と"!"
delegate?.callDelegateMethod()
label.setFont(font!)

上記のように変数の宣言時ではない"?"や"!"はオプショナル型ではありません。(これらの使い方は後述します)
swiftを学び始めたばかりの人は、ここを勘違いしてしまっている人が非常に多いと思います。



◼︎ ポイント
変数の宣言時以外で使用する"?"と"!"はオプショナル型とは別の意味を持つ。



オプショナル型の初期化

オプショナル型で宣言した場合と、非オプショナル型で宣言した場合の初期化の違いを見てみましょう。

オプショナル型

まずはオプショナル型です。
以下のように"?"か"!"を使ってオプショナル型の変数を宣言します。

オプショナル型の宣言
var hoge: String?
var fuga: Int!

そしてこれらの変数をprintlnメソッドを使って出力してみます。

オプショナル型の変数の中身
var hoge: String?
println(hoge)
# => nil
var fuga: Int!
println(fuga)
# => nil

"?"を使ったオプショナル型も、"!"を使ったオプショナル型もどちらもnilとなりました。
つまり、オプショナル型の変数は宣言をした段階ではnilが入っているということになります。

もちろん、以下のように値を入れて初期化をすればその値が代入されます。

値を入れた初期化
var hoge: String? = "Hello World"
println(hoge)
# => Optional("Hello World")

文字列"Hello World"がOptionalという記述に囲まれています。この記述に関しては後述するので今は値を入れて初期化すれば、nil以外の値が出力されるということだけ注目してください。

非オプショナル型

次に非オプショナル型を見てみましょう。
以下のように非オプショナル型の変数を宣言します。

非オプショナル型の宣言
var piyo: String

そしてこの変数piyoをprintlnメソッドを使って出力してみます。

オプショナル型の変数の中身
var piyo: String
println(piyo)
# => エラーして実行できない

実はこれは実行することができません。 「Variable 'piyo' used before being initialized」と怒られます。
つまり、非オプショナル型の変数は値を入れないと使うことができないということです。

オプショナル型の変数なら、値を入れないときにはnilが代入され実行することができました。しかし非オプショナルな変数の場合、値を入れないと変数には何も入らず(nilも入らない)エラーを起こしてしまいます。

非オプショナルな変数は使う前に必ず何らかの値を入れてあげなくてはいけません。

値を入れた初期化
var piyo: String = "Hello World"
println(hoge)
# => "Hello World"


◼︎ ポイント
オプショナル型の変数は何も値を入れなくてもnilとして使うことができるが、非オプショナル型の変数の場合はnil以外の値を代入するまで使うことができない。



nilの代入

オプショナル型の変数と、非オプショナルな変数にそれぞれnilを代入するとどうなるでしょうか。

オプショナル型

オプショナル型の変数にnilを代入してみます。

オプショナル型の変数にnilを代入
var hoge: String?
var fuga: Int!
hoge = nil
fuga = nil

問題なく実行できます。オプショナル型の変数はnilを扱うことができるためですね。

非オプショナル型

次に非オプショナル型の変数にnilを代入してみます。

非オプショナル型の変数にnilを代入
var piyo: String
piyo = nil
# => エラーして実行できない

**非オプショナル型の変数にはnilを代入することができません。**nilを代入しようとするとエラーして実行ができません。



◼︎ ポイント
非オプショナルな変数にはnilを代入することができない


まとめ

ここまでいろいろなオプショナル型、非オプショナル型についての比較を行ってきました。一旦整理してまとめましょう。

オプショナル型の特徴

  • オプショナル型で宣言した変数はnilを代入できるが、反対に非オプショナル型の変数にはnilを代入することができない
  • 変数をオプショナル型にするにはString、Intのようなデータ型の最後に"?"か"!"をつける
  • 変数宣言で用いる"?"・"!"とそれ以外で使う"?"・"!"は別物であり、変数宣言で使用する方がオプショナル型

オプショナル型と非オプショナル型の違い

オプショナル型 非オプショナル型
データ型(Stringの場合) String?またはString! String
nilの代入 可能 不可
初期値 nil 何もない
変数に値を代入しない場合 nil エラーが起きる

なぜnilが必要なのか(読み飛ばし可)

少し話が逸れますが、なぜアプリケーションが落ちる危険があるにも関わらずnilを扱うのでしょうか。

例えば次のような例を考えましょう。
Facebookではユーザーの名前は必須の項目ですが、画像の設定は任意です。

ユーザーの情報をプロパティとして持つ場合、名前nameと画像imageのデータは以下のように宣言することになります。

プロパティの定義
var name: String
var image: UIImage?

名前nameのデータ型はStringです。一方、画像imageのデータ型はUIImage?と、型名(UIImage)の最後に"?"がつきます。つまり、imageはオプショナル型ということです。

画像は必須に設定する項目ではないのでユーザーによってはデータが存在しない場合があります。そういったユーザーは変数imageは空、すなわちnilでなくてはいけません。
このようなパターンを実装する際にnilは必要となります。このnilを扱わなくてはいけないときに活躍するのがオプショナル型ということです。



◼︎ ポイント
オプショナル型を使うのはnilを扱うため。nilをプログラムで使うのは必須ではないデータやプログラム中で一旦破棄されるようなデータを扱う場合



オプショナル型

非オプショナル型の変数は普通に扱う変数です。一方nilを扱うことのできるオプショナル型の変数は通常とは扱い方が少し異なります。

オプショナル型の変数を通常の変数と同様に扱おうとするとおもわぬエラーが起きます。そのため、オプショナル型の値を通常の値に変換するアンラップという方法が必要になります。

では、オプショナル型の基本的な特徴を押さえていきましょう。

"?"と"!"の違い

変数宣言時に用いる"?"と"!"はどちらもオプショナル型です。しかし、この2つは少し特性が異なります。

一般的にオプショナル型(Optional Value)というと"?"の方を指します。
"!"は**暗黙的アンラップ型(Implicitly Unwrapped Optional)**と呼ばれるオプショナル型です。

繰り返しになりますが、"?"も"!"もnilを許容するオプショナル型です。

ここで「アンラップ」という単語が出てきました。後述しますが、アンラップはオプショナル型を扱うためには必要不可欠な処理です。



◼︎ ポイント
"?"も"!"もオプショナル型であるが、"!"は特に暗黙的アンラップ型(Implicitly Unwrapped Optional)と呼ばれるオプショナル型。



"?"による出力

少しややこしくなってしまったので、まずは一般的なオプショナル型"?"について見てみましょう。
以下のようなオプショナル型の変数hogeがあります。

オプショナル型の変数hogeの宣言
var hoge: String?

この状態ではhogeの中身はnilです。値が入っていないので当然ですね。

ではhogeに値を代入したあと、printlnメソッドで変数の中身を出力してみましょう。

オプショナル型の変数hogeの出力
var hoge: String?
hoge = "Hello World"
println(hoge)
// => Optional("Hello World")

ただの"Hello World"という出力ではなく、Optionalという記述がついています。
Int型ではどうなるでしょうか。

オプショナル型の変数hogeの出力
var hoge: Int? = 10
println(hoge)
// => Optional(10)

Int型でもただの10という出力ではなく、**Optional(10)**となります。

このOptionalがついた文字列Optional("Hello World")と通常の文字列"Hello World"は似ているようですが別物です。同じように扱うことはできないのです。



◼︎ ポイント
"?"のオプショナル型の変数は出力したときにOptionalという記述が含まれるようになる。


Optional(値)

この値がOptional(値)となってしまうことが、オプショナル型"?"と非オプショナル型の大きな違いです。

ただの「値」と「Optional(値)」は異なるものです。つまり、同様には扱えません。具体的な例を見てみましょう。

非オプショナル型の変数に入った数字の10とオプショナル型の変数に入った数字の10を足し合わせてみます。

非オプショナルの値とオプショナルの値を足し合わせる
var a: Int  = 10 // 非オプショナル型
var b: Int? = 10 // オプショナル型
a + b
// => エラーが起きる

結果はエラーで実行することができません。変数aも変数bも同じ「10」という数字を代入したのに足すことができないのです。

なぜなら、aは確かに「10」ですが、bは「Optional(10)」という値だからです。
10 + Optional(10)は計算することができません。

そこで、オプショナル型の値を通常の値(Optiona(10)を10)に変換するためにアンラップという処理が必要となります。



◼︎ ポイント
オプショナル型の変数に値を代入するとOptional(値)というオブジェクトに変換される。このOptional(値)は単なる値と同じようには扱えない。


アンラップ

そもそもOptional(値)とはどのような状態でしょうか。

**Optionalは値を包み込むラップ(包み紙)**のイメージです。オプショナル型は値をOptionalというラップ1枚で包み込んでいます。すると、たとえ中身がない(=nil)状態でも包み紙だけは存在するため、とりあえず扱うことができます。
オプショナル型の値がnilでも使えるのは、この包み紙が存在しているためです。

しかし、この便利な包み紙があるために値はラッピングされ、直接扱うことができません。扱うためにはラップを取り除き、中身の値を取り出さなくてはいけません。
この包み紙を取り除き、値を取り出すことをアンラップと言います。


【例】
var wrapNum: Int? = 10

この変数wrapNumはオプショナル型なので値10はラップされ、**Optional(10)**となります。

Optional()という包みに値「10」がラッピングされています。
wrapNumで足し算のような計算をするには、アンラップすることでwrapNumの値をOptional(10)から10に変換しなくてはいけません。



◼︎ ポイント
Optional()は値を包み込むラップで、その中から値を取り出すためにはアンラップという処理が必要となる。


アンラップの種類

アンラップの方法はいくつかあります。代表的なアンラップの方法は以下です。

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

よくわからない横文字の連続でツライですね...
ですが、これらの名前を覚える必要は全くありません。

すべて、目的はオプショナル型の変数から値を取り出すことです。それぞれ使うタイミングと記法が異なるだけなので、それをキチンと押さえることができればアンラップは怖くありません。

Forced Unwrapping

Forced Unwrapping(強制的アンラップ)はオプショナル型を強制的にアンラップする方法です。オプショナル型の変数の中にどんな値が入っていても関係なく、その値を取り出します。

強制的アンラップの記述方法は簡単です。オプショナル型の変数の後ろに"!"をつけます。

強制的アンラップ
var optional: Int? = 10 // オプショナル型
// そのまま出力
println(optional)
// => Optional(10)

// 強制的アンラップ("!"をつけて)で出力
println(optional!)
// => 10

"!"をつけずに出力した場合、今までと同じようにOptional(10)とOptionalに値が囲まれてしまいます。一方で、オプショナル型の変数に対して"!"をつけ強制的アンラップをすると、出力が10となりました。

アンラップすることで、オプショナル型のままでは出来なかった以下のような計算もできるようになります。

強制的アンラップ
var a: Int  = 10 // 非オプショナル型
var b: Int? = 10 // オプショナル型
a + b!
# => 20

オプショナル型の変数bは本来ならラッピングされているため値はOptional(10)となるのですが、"!"で強制的アンラップをすると、変数bは中身の値10となり他のInt型の値と計算が可能となります。

このように、オプショナルな変数の最後に"!"をつけることで、オプショナルに包まれた中身の値を取り出すことができます。

便利に見える強制的アンラップですが、欠点があります。
アンラップする対象のオプショナル型の変数の中身がnilだった場合、エラーしてアプリケーションが落ちてしまうことです。

nilに対する強制的アンラップ
var hoge: Int?
hoge!
# => オプショナル型の変数hogeはnilなのでアンラップするとエラーする

**アンラップをする場合には、必ずラッピングの中身が存在する(=nilではない)ことが保証されていなければいけません。**nilかどうかわからない場合は後述するオプショナルチェイニングかオプショナルバインディングを使いましょう。

一つ注意して欲しいのが、このアンラップに用いる"!"はオプショナル型の変数宣言の"!"とは別物ということです。



◼︎ ポイント
Forced Unwrapping (強制的アンラップ)はオプショナル型の変数の後ろに"!"をつけることでその変数を強制的にアンラップする方法。オプショナル型の変数の中身を取り出せて便利だが、中身がnilの場合はエラーしてしまうので注意が必要。


Optional Binding

強制的アンラップはオプショナル型の変数を中身の値に関係なくアンラップしました。そのため変数にnilが入ってしまうとアプリケーションが落ちてしまうという問題があります。

この問題を解決するアンラップの方法がオプショナルバインディングです。

オプショナルバインディングはif文などの条件式と組み合わせて使います。具体的な例を見てみましょう。

趣味を扱うための変数hobbyをオプショナル型で宣言します。オプショナルバインディングを使って、hobbyに値が入っていればその値を出力し、なければ(=nilならば)「趣味はありません」と出力するようにします。

オプショナルバインディング
var hobby: String? // オプショナル型

if let unwrappedHobby = hobby {
    println(unwrappedHobby)
}
else {
    println("趣味はありません")
}

オプショナルバインディングの特徴は条件式を用いることです。この条件式はアンラップする対象のオプショナル型の変数がnilかどうかを判定するためのものです。

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

この形がオプショナルバインディングです。条件式として、**オプショナル型の変数を異なる変数に代入します。**この変数はlet(定数)でもvar(変数)でも構いません。

値が入っている場合(nilでない)

オプショナル型の変数に値が入っている場合、その値がifの後の変数に代入されます。つまり、上の例では変数hobbyがnilでないとき以下のようになるということです。

オプショナルバインディング(オプショナル型の変数がnilでない場合)
var hobby: String? = "プログラミング"

# unwrappedHobbyに"プログラミング"が代入される
if let unwrappedHobby = hobby {
    # hobbyがnilではないため、ここの処理が呼ばれる
    println(unwrappedHobby)
    # => "プログラミング"
}

出力された値にはOptionalがついていないことに注目してください。つまり、条件式で代入された変数はオプショナル型の変数がアンラップされたものとなります。
上の例では、変数unwrappedHobbyにはオプショナル型hobbyがアンラップされた値が代入されます。

nilの場合

次に、オプショナル型の変数の中身がnilの場合を見てみましょう。nilのときは条件式がfalseとなります。

オプショナルバインディング(オプショナル型の変数がnilの場合)
var hobby: String?

if let unwrappedHobby = hobby {
    println(unwrappedHobby)
}
else {
    # hobbyがnilのため、ここの処理が呼ばれる
    println("趣味はありません")
    # => "趣味はありません"
}


◼︎ ポイント
オプショナルバインディングを使うと、オプショナル型の変数に値が入っていればアンラップして処理を行い、値がない(=nil)のときには処理を行わない、または違う処理を行うことができる。


Optional Chaining

オプショナルチェイニングもオプショナル型の変数の中身がnilのときに安全にプログラムを実行するための機能です。
オプショナルチェイニングの使い方はオプショナル型の変数のあとに"?"をつけます。

オプショナル型の変数?

オプショナルチェイニングはオプショナル型の変数に続けてプロパティを取得したり、メソッドを呼び出す場合に使用します。

【例】
オプショナル型の変数?.プロパティ
オプショナル型の変数?.メソッド()

オプショナルチェイニングもオプショナル型の変数がnilかどうかでその後の処理が変わります。

値が入っている場合(nilでない)

オプショナル型の変数に値が入っている場合、オプショナルチェイニングは**変数をアンラップし、中身を取り出します。**そして、それに続くプロパティを取得したり、メソッドを呼び出すことができます。

しかし、ここで一つ気をつけなくてはいけません。
それは、オプショナルチェイニングに続けて取得したプロパティやメソッドの戻り値はオプショナル型になるということです。

オプショナルチェイニング(オプショナル型の変数がnilでない場合)
var human: Human? = Human()

// nilでないためプロパティが取得できる
human?.name
// => "Optional(シンボ)"

// nilでないためメソッドを呼び出せる
human?.hello()
// => "Optional(こんにちは)"

オプショナルチェイニングを使って取得した値はすべてオプショナル型となるので、その値を使うには再度アンラップが必要になります。

nilの場合

オプショナル型の変数の中身がnilの場合、オプショナルチェイニングはnilを返します。そしてnilを返した後、それに続く処理をすべてキャンセルします。

つまりnilに対してプロパティを取得しようとしたり、メソッドを呼び出すことがなくなるため安全に処理を記述することができます。

オプショナルチェイニング(オプショナル型の変数がnilの場合)
var human: Human?

// humanがnilのため、nilが返る
human?.name
// => nil

// humanがnilのため、nilが返る
human?.hello()
// => nil

先ほど、「オプショナルチェイニングを使って取得した値はすべてオプショナル型となる」と言いましたが、その理由はオプショナル型の変数がnilのときは返る値がnilになるためです。
nilを扱うことができるのがオプショナル型だけなので、nilが返る可能性がある以上、値はオプショナル型にしなくてはいけません。



◼︎ ポイント
オプショナルチェイニングを使えば、オプショナル型の変数の中身がnilの可能性があっても安全にプロパティを取得したり、メソッドを呼び出せる。ただし、返る値はオプショナル型となるので注意が必要。



暗黙的アンラップ型"!"

最後に、暗黙的アンラップ型"!"の説明をします。この"!"は強制的アンラップの"!"とは別物で、"?"同様オプショナル型であることを示すものです。

暗黙的アンラップ型と強制的アンラップの違い
// 暗黙的アンラップ型
var unwrappedInt: Int!

// 強制的アンラップ
10 + wrappedInt!

暗黙的アンラップ型"!"はデータ型なので、変数の宣言時に使用する"!"のことを指します。
もう一つのオプショナル型である"?"との違いは、使用するとき必ず強制的アンラップをすることです。

オプショナル型"?"の値は、そのまま使うとOptional()によってラッピングされるので通常の値と併用して使うことができません。

オプショナル型と非オプショナル型の計算
var a: Int  = 10 // 非オプショナル型
var b: Int? = 10 // オプショナル型
a + b
# => エラーが起きる

そのため、強制的アンラップ"!"でアンラップしてから使用します。

強制的アンラップ"!"
var a: Int  = 10 // 非オプショナル型
var b: Int? = 10 // オプショナル型
a + b!
# => 20

しかし、オプショナル型を"?"ではなく暗黙的アンラップ型"!"で宣言すればアンラップする必要がありません。なぜなら使用するときに自動でアンラップをしてくれるからです。

暗黙的アンラップ型"!"
var a: Int  = 10 // 非オプショナル型
var b: Int! = 10 // 暗黙的アンラップ型"!"
a + b
# => 20

暗黙的アンラップ型"!"はいちいちアンラップをする手間が省けます。しかし、強制的アンラップと同様に変数の値がnilの場合はエラーしてアプリケーションが落ちてしまうので注意が必要です。

暗黙的アンラップ型は主に、最初はnilで宣言したいが使うときには絶対に値が入っているようなときに使用します。



◼︎ ポイント
暗黙的アンラップ型"!"の変数はオプショナル型であるためnilを代入することができるが、使用するときには自動でアンラップしてくれるためそのまま使える。しかし、変数の値がnilのときにはエラーしてしまう。



まとめ

オプショナル型とアンラップについてまとめましょう。

アンラップ

  • オプショナル型は値をラッピングしているため、そのままでは値を扱うことができない。値を扱うにはこのラッピングを取り外す「アンラップ」という処理が必要。
  • アンラップには、「強制的アンラップ」、「オプショナルバインディング」、「オプショナルチェイニング」の3つの方法がある。
  • 暗黙的アンラップ型"!"でオプショナル型を宣言すれば自動でアンラップしてくれる。

アンラップの方法

1. 強制的アンラップ
オプショナル型の変数の後ろに"!"をつけて使用する方法。"!"をつけたオプショナル型の変数を強制的にアンラップして値を取り出すことができるが、変数の中身がnilのときはエラーしてしまう。

強制的アンラップ
var a: Int? = 10
a! // 強制的アンラップ

2. オプショナルバインディング

if文などの条件分岐を使ってオプショナル型の値がnilかどうかで処理を分ける方法。条件式では
if let 定数名 = オプショナル型の変数 { 処理 }
のように定数や変数にオプショナル型の値を代入する。

このとき、オプショナル型の変数がnilでなければ左辺の定数、または変数にオプショナル型の変数をアンラップした値が代入される。

オプショナルバインディング
var hobby: String?

if let unwrappedHobby = hobby {
    // オプショナル型の値がnilでないとき
    println(unwrappedHobby)
    // => hobbyをアンラップした値が出力される
}
else {
    // オプショナル型の値がnilのとき
    println("趣味はありません")
}

3. オプショナルチェイニング

オプショナル型の変数の後ろに"?"をつけて、そのあと続けてプロパティにアクセスしたりメソッドを呼び出す方法。
このとき、オプショナル型の変数がnilでなければ、そのあとのプロパティの取得やメソッドの呼び出しができる。しかしオプショナル型の変数がnilのときはプロパティの取得などはキャンセルされ、nilが返る。

また、nil以外で返ってくる値はすべてオプショナル型となる。

オプショナルチェイニング
var human1: Human? = Human()
var human2: Human?

// nilでないためプロパティが取得できる
human1?.name
// => "Optional(シンボ)"

// nilのため、メソッドは呼び出されずnilが返る
human2?.hello()
// => nil


アンラップの方法の選び方

06.png

まとめのまとめ

最後にすべてのまとめです。

オプショナル型と非オプショナル型の違い

  • オプショナル型の変数はnilの代入が可能であるが、非オプショナル型の変数はnilを代入できない
  • オプショナル型の変数の宣言には、データ型の最後に"?"か"!"をつける

オプショナル型の扱い

  • オプショナル型を非オプショナル型と同様に扱うには「アンラップ」という処理が必要
  • アンラップをしない場合、オプショナル型の値にはOptional()というラッピングがされる

アンラップの方法

  • オプショナル型の宣言時に"!"を使うと、自動でアンラップされるようになる
  • アンラップには「強制的アンラップ」、「オプショナルバインディング」、「オプショナルチェイニング」の3つの方法がある。
  • 「強制的アンラップ」はオプショナル型の変数に最後に"!"をつけて強制的にアンラップする方法
  • 「オプショナルバインディング」は条件式を使って、オプショナル型がnilでないときだけアンラップして処理をおこなう方法
  • 「オプショナルチェイニング」はオプショナル型の変数に最後に"?"をつけて、オプショナル型がnilでないときだけ続けてプロパティを取得したり、メソッドを呼び出す方法で取得できる値はすべてオプショナル型になる
2077
1784
24

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2077
1784

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?