【swift】Optional型について理解する

## はじめに
Optional型について、アンラップの使い分けなど理解しきれていない部分があったため、学習した内容をまとめます。

## Optional型とは
値があるか空かの、いずれかの値を表す型を**Optional型**といいます。
swiftの変数や定数は基本的に**nil**（値が存在しないこと）を許容しませんが、nilを許容する必要がある場合はOptional型を使用します。

## Optional型のアンラップ
Optional型は値を持っていない可能性があるため、そのまま代入したりTextに使用したりするとエラーが発生してしまいます。
そのため値をオプショナル型から取り出す必要があり、この作業をアンラップといいます。
アンラップには次の3つの方法があります。
- **オプショナルバインディング**
- **??演算子**
- **強制アンラップ**

それぞれのアンラップ方法について解説していきます。

## オプショナルバインディング
条件分岐や繰り返し文の条件にOptional型の値を指定するアンラップ方法を、**オプショナルバインディング**といいます。
オプショナルバインディングはif let文を用いて行います。
値を持つ場合には左辺の定数に値が代入され、if文内の{}の処理が実行されます。
nilの場合には{}内の処理はスキップされます。

![スクリーンショット 2025-03-14 11.34.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/5973908d-a25e-45b1-98d8-de1a1a355738.png)

nilの場合のみ実行する文を追加するには、else節を追加します。

![スクリーンショット 2025-03-14 11.41.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/71075e6e-a3f6-4926-b911-01b2c1054db5.png)

if let文では複数のOptional型の値を同時に取り出すことができます。
Optional型の値を `,` 区切りで並べると、全てのOptional型が値を持っていた場合のみ処理が実行されます。
以下の例では、2つのString?型の定数OptionalAとOptionalBを用意し、どちらも値があった場合に2つのString型の定数aとbを利用できます。

![スクリーンショット 2025-03-14 12.22.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/29b82c27-1d5e-4cb3-a7e9-cc78e6e3a9f8.png)

if let文同様、guard let文でもOptional型のアンラップが可能です。
if let文との違いは、guard let文で宣言された変数や定数は、guard let文以降で利用可能という点です。
これは、条件式が満たされなかった場合にはスコープから退出するため、guard文以降では変数や定数の存在が保証されているためです。
次の例では、guard let文で宣言した定数intにアクセスしています。

![スクリーンショット 2025-03-14 14.40.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/f92ebb6c-be78-43c5-b4ec-faac9a870452.png)

### if let文とguard let文の使い分け
2つの違いは、guard let文は早期退出に適した制御構文であるという点です。
比較例として、2つのInt?型の引数を受け取り、両方とも値を持っていればその輪を返し、どちらかが値を持っていなければnilを返すと同時に値を持っていない引数を出力するプログラムを考えます。

if文で実装する場合は、if let文で宣言した定数は{}外で使用できないため、if let文の外にInt型の定数を宣言しておく必要があります。if let文でInt?型の引数の値が確認できた場合はその定数に代入を行い、確認できなかった場合はreturn文でnilを返して処理を終了します。

![スクリーンショット 2025-03-14 16.33.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/6abf89aa-f324-4a94-8370-5cb1e66edcaf.png)

guard文で実装する場合は、guard let文で宣言した定数は{}外でも使用できるため、guard let文の外にInt型の定数を宣言しておく必要はありません。

![スクリーンショット 2025-03-14 16.55.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/71c4d41b-ac54-41ab-9de3-50845d2aaedd.png)

このように、条件に応じて早期退出するコードはguard文を使用して実装した方がシンプルとなります。また、guard文では退出処理を書き忘れた場合にコンパイルエラーとなるため、単純ミスを未然に防げます。

## ??演算子
Optional型に値が存在しない場合のデフォルト値を指定するには、??演算子を使います。
??演算子は左辺にOptional型の値、右辺に値を持っていない場合に代入される値を取ります。

![スクリーンショット 2025-03-14 17.00.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/e2b333ef-b313-4829-b3b8-ba345277ab7b.png)

上記の例では、??演算子の左辺にInt型の値1を持ったInt?型の定数optinalIntを、右辺にInt型の値3を指定し、結果として左辺の値1を取得しています。

![スクリーンショット 2025-03-14 17.06.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/d80ce1bc-aed3-4473-9cfb-436e606124a0.png)

左辺のInt型の定数optinalIntにnilが入っている場合には、結果として右辺のInt型の値3を取得します。

## 強制アンラップ
強制アンラップは、Optional型から値を強制的に取り出す方法です。
値が存在しない場合、実行時エラーとなります。
強制アンラップを行うには、!演算子を使います。

![スクリーンショット 2025-03-14 17.10.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/79e5f918-1dab-4483-8997-561fa79ed3d4.png)

上記の例では、Int?型の2つの定数からInt型の値を強制的に取り出してそれらを足しています。

強制アンラップは値がないケースを無視したシンプルなコードを可能にしますが、一方で実行時エラーの危険性をはらんでいます。
そのため、値の存在がよほど明らかな箇所や、値が存在しなければプログラムを終了させたい箇所以外では、強制アンラップの使用は避けた方が良いです。

## まとめ
- 値があるか空かの、いずれかの値を表す型を**Optional型**という
- Optional型の値はそのまま使用するとエラーとなるため、アンラップして使用する
- アンラップは主に**if let文**、**guard let文**、**??演算子**、**強制アンラップ**がある
- 強制アンラップは値が存在しなかった場合にエラーとなるため、基本的にはif let文、guard let文、??演算子を用いて安全にアンラップするのが望ましい。