存在しない彼女へのアクセスによって起きるぬるぽをKotlinのNull Safetyの力で防ぐ

# 今日はなんの日？
今日はバレンタインらしいですが、特に変わったことがないのでいつも通りの記事を書きたいと思います。
# とあるコード
```java
import java.util.Calendar;

class Chocolate {}

class Kanojo {
    private Chocolate choco = new Chocolate();

    Chocolate getChoco() {
        return choco;
    }
}

class Naotiki {
    private Kanojo kanojo;
    Kanojo getKanojo() {
        return kanojo;
    }

    void eat(Chocolate choco){
        System.out.println("おいし～");
    }

    public static void main(String[] args) {
        //私のインスタンスを生成
        Naotiki naotiki= new Naotiki();
        Calendar calendar = Calendar.getInstance();
        //バレンタインなら？
        if (calendar.get(Calendar.MONTH) == Calendar.FEBRUARY && calendar.get(Calendar.DAY_OF_MONTH) == 14) {
            //チョコがもらえる・・・？
            Chocolate choco = naotiki.getKanojo().getChoco();
            naotiki.eat(choco);
        }
    }
}
```
ふむふむ・・・
`main()`が実行されると私のインスタンスが作られ、もし2/14なら私の`Kanojo`を取得しチョコをもらうんだな！
そして私がありがたく美味しく頂くということか・・・
完璧なコードだな。間違いない。

さて、実行してみるか。

```text:例外
Exception in thread "main" java.lang.NullPointerException: 
Cannot invoke "Kanojo.getChoco()" because the return value of "Naotiki.getKanojo()" is null
	at Naotiki.main(Valentine.java:32)
```

あれ・・・？

意訳
>ぬるぽ
>`Naotiki.getKanojo()`の返り値が**Null**なので`Kanojo.getChoco()`が実行できませんでした

あ・・・・(察し)
うわぁぁぁぁぁぁぁぁ！！！！！！(ぬるぽでクラッシュする音)

なんということでしょう。
彼女がNullの可能性を考慮しなかったが為に、2/14にぬるぽでクラッシュしてしまう悲しい私が生まれてしまったのです。
これでは一生2/14に怯えて暮らさなければなりません。

これでは良くないですね。
Kotlinを使ってNull Safetyにしてあげましょう。

```kotlin
import java.util.*

class Chocolate
class Kanojo {
    var choco: Chocolate = Chocolate()
        private set
}

class Naotiki {
    var kanojo: Kanojo? = null
        private set

    fun eat(choco: Chocolate) {
        println("おいし～")
    }
}

fun main(args: Array<String>) {
    //私のインスタンスを生成
    val naotiki = Naotiki()
    val calendar = Calendar.getInstance()
    //バレンタインなら？
    if (calendar[Calendar.MONTH] == Calendar.FEBRUARY && calendar[Calendar.DAY_OF_MONTH] == 14) {
        //チョコがもらえる・・・？
        val choco = naotiki.kanojo.choco
        naotiki.eat(choco)
    }
}
```
とりあえずKotlinに変換してみました。
初期値がないといけないので今回はNullを代入しておきます。
併せて、`Kanojo`はNull許容の`Kanojo?`にします。
するとIntelliJくんがなにか言いたそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357553/f6f49f6a-521a-d6cf-286d-71b1096735e7.png)

>`Kanojo?` の Null 許容レシーバーでは、安全な (`?.`) または非 Null アサート (`!!.`) 呼び出しのみが許可されます。

なるほど、Nullかもしれないものはそのまま呼び出せないんですね。
`!!.`を使うと先程と同じ結果になってしまうので安全な方の`?.`を使いましょう。
```diff_kotlin
fun main(args: Array<String>) {
    //なおちきのインスタンスを生成
    val naotiki = Naotiki()
    val calendar = Calendar.getInstance()
    //バレンタインなら？
    if (calendar[Calendar.MONTH] == Calendar.FEBRUARY && calendar[Calendar.DAY_OF_MONTH] == 14) {
        //チョコがもらえる・・・？
-       val choco = naotiki.kanojo.choco
+       val choco = naotiki.kanojo?.choco
        naotiki.eat(choco)
    }
}
```
ん？
また何かIntelliJが言いたそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357553/07faa1f4-661f-edc1-b1c4-cd084776adec.png)

`kanojo`がNullかもしれないので`?.`でアクセスした`choco`もNullかもしれない型になるんですね！
Null許容チョコは`eat()`出来ないので怒られていますね。
`?.let { ... }`をうまく使って書いてみましょう。
```diff_kotlin
fun main(args: Array<String>) {
    //なおちきのインスタンスを生成
    val naotiki = Naotiki()
    val calendar = Calendar.getInstance()
    //バレンタインなら？
    if (calendar[Calendar.MONTH] == Calendar.FEBRUARY && calendar[Calendar.DAY_OF_MONTH] == 14) {
        //チョコがもらえる・・・？
        val choco = naotiki.kanojo?.choco
-       naotiki.eat(choco)
+       naotiki.kanojo?.let { she ->
+           naotiki.eat(she.choco)
+       }
    }
}
```
`kanojo`がNullじゃないときに`let`が実行され、その中でNullではないことが保証された`kanojo`(let内では`she`)から貰った`choco`を`eat()`するんですね。
もし`kanojo`がNullなら何も実行されずにそのまま終了するようです。

直し終わったところで・・・
2回目の実行です！

```text
java.exe (省略)

プロセスは終了コード 0 で終了しました
```
やりました！ぬるぽを回避し私に平穏な2/14が戻ってきました！

#### 私の彼女がNullではない世界線の実行結果
```text
java.exe (省略)
おいし～

プロセスは終了コード 0 で終了しました
```

# おわり
久しぶりにQiita書きたくなったので書きました。
書いてて私は悲しくなりました。[^1]
[^1]:Q. なにも行動しないお前が悪いのでは？ A. その通りです。(泣)

コメントで:chocolate_bar:(`:chocolate_bar:`)をくれると私が喜びます

KotlinのNull Safetyについて、詳しくはこちらを見てください

https://kotlinlang.org/docs/null-safety.html