【カタカナ禁止で】初心者のためのSwiftの"?"と"!"

# はじめに
**プログラミングにはカタカナ語が多すぎる！！！！！**
***
Swiftをやってて、これらのエラーに当たったことはありませんか？

- `Value of optional type 'Int?' must be unwrapped to a value of type 'Int'`
- `Coalesce using '??' to provide a default when the optional value contains 'nil'`
- `Force-unwrap using '!' to abort execution if the optional value contains 'nil'`

で、どういう意味かと思って調べてみたものの、「*オプショナル*」だとか「*アンラップ*」だとかの**カタカナ語**を前にして挫けたことありません？
それで結局、よく分からずに`Fix`を押して、「なんでか知らんけどエラー消えたしいいや」ってなってませんか？

この記事を頑張って読めば、これらのエラーの原因がちゃんと分かるようになります。

### 注意書き
- `?`と`!`の基礎だけを簡単に理解できるようにしたために、紹介しきれなかった概念などが少しあります。

- この記事は、以下の内容を分かっている前提で話を進めていきます。
    - 変数や型について(`Int`や`String`など)
    - `if`文などの基礎的な文法

- 「カタカナ禁止」を謳ってはいますが、「エラー」などの最低限のカタカナ語は使います。お許しを…。

# まずは前提知識から
## 空っぽ(`nil`)という概念
冒頭のエラーについて理解するには、まず初めに`nil`という概念について理解する必要があります。

`nil`というのは、**変数の中が空っぽだよ、何も入ってないよ**ということを表す概念です。

少し強引ですが、「`nil`についてよう分からん」ってなったら、とりあえず頭の中で`nil`を「空っぽ」と読んでください。だいたい合っているはずです。

***
★重要★　`nil`は「空っぽ」を表す。
***

## `nil`の使いどころ
例えば、会員登録の際のデータとして、**任意で**年齢を知りたいという場合について考えてみます。(「**任意で**」というのがとても重要です。)

年齢は間違いなく整数ですから、データは`Int`型の変数で持っておけば良さそうですね。

ところが、「**任意で**知りたい」というのが厄介です。
年齢の入力が任意ということは、「年齢の欄に何も入力されない」という場合も考えられるわけです。

そこで、年齢の欄に何も入力されていなければ、変数の中身を、「空っぽ」であることを表す`nil`にしておきます。
こうすることで、**「年齢が入力されなかった」ということを、`nil`によって知ることができる**のです。

## 「普通の変数」も見ておこう
実際にプログラムで`nil`を使う手順について説明する前に、まずは前提知識として、皆さんがいつものように使っている「普通の変数」について考えてみます。

Swiftにおいて、「普通の変数」には必ず何かしらの「値」が入っていなければなりません。
(ここで言う「値」というのは、例えば`String`型の変数では何かしらの文字列、`Int`型の変数では何かしらの数字…などといった具合です。)

つまり、Swiftの「普通の変数」において、「変数の中身が空っぽ」というようなことは想定されていないのです。
そのため、Swiftで`nil`を扱うには、その変数を宣言するときに、**「普通の変数」を使うときとは違うこと**をしなければなりません。

## `nil`を代入できる変数を使う
変数に`nil`を代入するには、**型の名前の後ろに`?`をつけます**。

```swift:例1：nilを代入できる変数の宣言
let hoge: Int = 0 //空っぽ(nil)を代入できない🙅‍♂️
let fuga: Int? = nil //空っぽ(nil)を代入できる🙆‍♂️
```

上の「例1」では、`fuga:`の後ろの`Int`にくっついている`?`がそれです。
`?`をつけることで、「`nil`も代入できる」ということが分かりやすくなりますね。

>ちなみに！
変数名になっている`hoge`や`fuga`というのは、「何でも良い、特別な意味のない名前」で、よくサンプルのプログラムなどで使われているものです。
このような「意味のない名前」のことを、難しい用語で「メタ構文変数」と呼びます。

***
★重要★　`?`をつければ、変数に`nil`を代入できる。
***

# 実際に`nil`を使うときの注意点
ここからは、**`nil`を代入できる🙆‍♂️ 変数**を使うときの注意点について話します。

## なぜ`?`をつけて区別するの？
みなさん、疑問に思いませんか？
>なんでわざわざ`?`をつけて普通の変数と区別するの？
普通の変数に直接`nil`を代入しちゃえば良くない？
>
>↓こんな感じで↓
```swift:例2：こんな感じで書いちゃえば良くない？
let hoge: Int = nil //?をつけていないのにnilを代入しているので、もちろんエラー❌
```

では、なぜ「例2」のように書けないのでしょう？

答えは、**「`nil`も代入できる」というのがなかなか厄介だから**です。

## `nil`の厄介な一面
その厄介な点というのは、**プログラムの中で`nil`を直接扱うと、エラーとなり、アプリが落ちてしまうこと**です。

**`nil`を代入できる🙆‍♂️ 変数**には、常に「もしかしたら中身が`nil`かもしれない」という可能性があります。
そのような、「もしかしたら中身が`nil`かもしれない変数」をプログラムでそのまま使ってしまうと、実際に中身が`nil`だった場合にエラーとなり、アプリが落ちてしまいます。

使っているアプリが突然落ちるなんて、勘弁してほしいですよね。

## 「`nil`によるエラー」を防ぐための取り組み
そのような`nil`によるエラーを防ぐために、Swiftでは
**1. `nil`を代入できない🙅‍♂️ 変数** と
**2. `nil`を代入できる🙆‍♂️ 変数**
の2つを**同じように扱えない**ようになっています。

↓具体的にはこんな感じ↓

```swift:例3：nilを代入できない🙅‍♂️変数 と nilを代入できる🙆‍♂️変数 を同じように扱ってしまう例
let hoge: Int = 0 //nilを代入できない🙅‍♂️
let fuga: Int? = 1 //nilを代入できる🙆‍♂️

print(hoge + fuga) //nilを代入できない🙅‍♂️ と nilを代入できる🙆‍♂️ を同じように扱ったのでエラー❌
```

「例3」で、`hoge`は`Int`となっているので **`nil`を代入できない🙅‍♂️ 変数**、`fuga`は`Int?`のように`?`がついているので **`nil`を代入できる🙆‍♂️ 変数**です。
`print(hoge + fuga)`のところでは、**`nil`を代入できない🙅‍♂️ 変数**と **`nil`を代入できる🙆‍♂️ 変数**を**同じように扱ってしまっている**ため、エラーになってしまっているのです。

***
★重要★  `Int`と`Int?`は同じように扱えない。
***

## `nil`にまつわる「型」の話
では、**`nil`を代入できない🙅‍♂️ 変数**と **`nil`を代入できる🙆‍♂️ 変数**のどこが違うために、同じように扱えないのでしょう？

実は、これら2つの変数の違いには「型」が関係しています。
(ここで言う「型」は、`String`型や`Int`型と言うときの「型」と同じようなものだと考えてください。)

このことについて、先ほどの「例3」の事例で説明すると、**`Int`となっている`hoge`と、`Int?`となっている`fuga`が、同じように見えて実は違う「型」だということ**です。

ここでひとつ、考えてみてほしいんですが、下の「例4」のように、`String`型の変数と`Int`型の変数をまぜこぜにして扱えませんよね。

```swift: 例4：これがエラーになるのと同じこと
print("こんにちは" + 3) //String + Intは計算できないのでエラー❌
```

これと同じように、**`nil`を代入できない🙅‍♂️ 変数**と **`nil`を代入できる🙆‍♂️ 変数**においても、**そもそも型が違うのでまぜこぜにして扱えない**のです。

>ちなみに！
`Int?`のような「`?`付きの型」には、「オプショナル型」という名前がついています。

***
★重要★ `Int`と`Int?`は違う「型」
***

## 型をそろえる / `?`を取る
つまり、「例3」のような計算をするためには、まず「`Int?`を`Int`に変換して、型をそろえる作業」が必要なのです。
これもう少し簡単に言うと、**「`?`を取る作業」** となります。

「例3」では、この作業をしなかったのでエラーになったというわけです。

***
★重要★　**`nil`を代入できる🙆‍♂️ 変数**を使う前に、「`?`を取る作業」が必要
***

# `?`の取り方3選
以下では、「`?`を取る3つの代表的な方法」について、順番に見ていきます。

## ひとつめ：　`!`
一つ目は`!`です。これは**簡単に使えますが、力技**です。

### `!`の使い方
**`nil`を代入できる🙆‍♂️ 変数**の後ろに`!`をつけます。

この`!`によって、変数の中身に関わらず**強制的に**`?`が取れます。
(「**強制的に**」というのがとても重要です。)

```swift:例5：fugaが1の場合
let hoge: Int = 0
let fuga: Int? = 1

print(hoge + fuga!) //fugaの"?"を取って計算している。結果は1⭕️
```

しかし、はじめに力技と言った通り、**この方法は万能ではありません**。

下の「例5」のように、`fuga`の中身が`nil`の場合、`!`を使うとエラーとなってアプリが落ちてしまいます。

```swift:例6：fugaがnilの場合
let hoge: Int = 0
let fuga: Int? = nil //例4と例5では、ここが"1"から"nil"に変わった

print(hoge + fuga!) //nilに対して"!"を使えない。よってエラーとなる❌
```

そのため、この方法は、**変数の中身が確実に`nil`ではないと分かっているとき**しか使えません。

## ふたつめ： `??`
二つ目は`??`です。これも、簡単に使えます。

### `??`の使い方
**`nil`を代入できる🙆‍♂️ 変数**の後ろに`??`をつけ、さらにその後ろに、**`nil`だった場合に代わりに使う値**を書きます。

こうすることで、**変数の中身が`nil`だった場合に、その代わりとして`??`の後ろの値が使われます**。

```swift:例7：hogeが1の場合
let hoge: Int? = 1

print(hoge ?? 0) //hogeがnilではないので、hogeの値がそのまま出力される。結果は1⭕️
```

```swift:例8：hogeがnilの場合
let hoge: Int? = nil

print(hoge ?? 0) //hogeがnilなので、??の後ろの値が出力される。結果は0⭕️
```

`??`を使う場合、中身が`nil`だった場合の「身代わり」となる値が後ろに用意されています。
そのため、`!`を使ったときのように、エラーとなってアプリが落ちることがありません。

つまり、、**`??`を使う方が、`！`を使うよりも安全に`nil`を扱うことができます**。

## みっつめ： `if let`
三つ目は`if let`です。
こちらは少し難しいですが、理解さえすれば`nil`を扱うときの幅が大きく広がります。

### `if let`の使い方
新たに用意した変数に **`nil`を代入できる🙆‍♂️ 変数**を入れてみて、**その中身が`nil`じゃない場合にのみ**`if`文の処理を行います。

逆に、もし変数の中身が`nil`だった場合、**`if`文の処理は行われません**。

```swift:例9：基本の使い方
let hoge: Int? = 1

if let fuga = hoge { //とりあえずfugaにhogeを代入 → 中身がnilじゃなかったらif文の処理を行う
    print(fuga)
    print("nilじゃなかったよ😊")
}
//結果⭕️
//1
//nilじゃなかったたよ😊
```

また、`else`を追加することで、**変数の中身が`nil`だった場合に行うべき処理**も書けます。

```swift:例10：elseで中身がnilの場合の処理を追加
let hoge: Int? = nil

if let fuga = hoge {
    //ここは中身がnilじゃない場合に実行される (この例では、hogeの中身がnilなので実行されない)
    print(fuga)
    print("nilじゃなかったよ😊")
} else {
    //ここは中身がnilだった場合に実行される
    print("nilやんけ😡")
}
//結果⭕️
//nilやんけ😡
```

このように、`if let`では、**変数の中身が`nil`でない場合にのみ**行うべき処理を書くことができます。
また、**変数の中身が`nil`だった場合とそうでない場合で、行うべき処理を明確に分けられる点**も、`if let`の特徴だということができます。

>ちなみに！
これまでに3つ見てきた「`?`を取る作業」には、「アンラップ」という名前がついています。

# まとめ
- `nil`は「空っぽ」を表す。
- 型の名前の後ろに`?`をつければ、変数に`nil`を代入できる。
- `Int`と`Int?`は違う「型」
- **`nil`を代入できる🙆‍♂️ 変数**を使う前に、「`?`を取る作業」が必要

# おわりに
この記事は、初心者の理解のとっかかりになればと考えて書きました。
そのため、「`guard let`」や「オプショナルバインディング」など、説明を省いた概念や用語があります。

もし「もっと学びを深めたい」ということでしたら、下の記事を読むのが良いと思います。
この記事では説明できなかった概念や用語なども含めて、とても分かりやすく説明されています。

https://qiita.com/maiki055/items/b24378a3707bd35a31a8#forced-unwrapping

最後に、誤字や脱字があったり、内容が誤っていたりしたら教えていただけると嬉しいです。