彡(ﾟ)(ﾟ)「KotlinでListにaddできない！なんでや！」(´・ω・｀)「それはね」

## やきうのお兄ちゃんはKotlinで困っていました。

彡(ﾟ)(ﾟ)「なんで高橋由伸を巨人に入れられへんねん！これ以上由伸を苦しめるなや！」

```kotlin:giants.kt
fun main() {

    val giants : List<String> = listOf("阿部")

    giants.add("高橋") // コンパイルエラー
}
```

(´・ω・｀)「どうしたの?」

## mutable~Of()を使っているか？
(´・ω・｀)「Kotlinでは `listOf()` `mapOf()` `setOf()` らの関数は **読み取り専用** のコレクションを返すんだ。だから書き込みである `add()` はできないんだよ。」

彡(ﾟ)(ﾟ)「ほんならどうやって書き込むねん」

(´・ω・｀)「**書き込み可能**なコレクションに変えれば大丈夫だよ、`mutableListOf` `mutableMapOf` `mutableSetOf` 関数を使おうね。」

彡(ﾟ)(ﾟ)「`var`とか`val`とかあるやん、あれと違うんか？」

(´・ω・｀)「いい質問だね。でもちょっと違うよ。そこが、**変更不可** ではなく **読み取り専用** とわざわざ言う必要がある理由なんだ。`var`はあくまで再割り当てが可能、`val`は再割り当てが不可能という特徴を持つよ。詳しくはコードを見たほうが早いね！」

```kotlin
fun main() {

    // 再割り当てテスト用のリスト
    var list0 = mutableListOf<Int>()

    // var 再割り当て OK / murableListOf 要素の書き込み OK 
    var listA = mutableListOf<Int>(1)
    listA.add(2)  // エラーにならない
    listA = list0 // エラーにならない

    // var 再割り当て NG / murableListOf 要素の書き込み OK
    val listB = mutableListOf<Int>(1)
    listB.add(2)  // エラーにならない
    listB = list0 // 再割り当てしてしまっているのでエラー

    // var 再割り当て OK / murableListOf 要素の書き込み NG
    var listC = listOf<Int>(1)
    listC.add(2)  // コレクションに書き込んでいるのでエラー
    listC = list0 // エラーにならない

    // var 再割り当て NG / murableListOf 要素の書き込み NG
    // いうなれば、こいつが変更不可
    val listD = listOf<Int>(1)
    listD.add(2)  // コレクションに書き込んでいるのでエラー
    listD = list0 // 再割り当てしてしまっているのでエラー

}
```

(´・ω・｀)「こういう関係性になっているよ。混乱してしまうかもしれないけど、じっくり読んでみてね。何回か使えば覚えられるよ。」

彡(ﾟ)(ﾟ)「ほうほうなるほど・・・。でも、 **まだコンパイルエラーになっとるぞ！** めん玉えぐったる！」


```kotlin:giants.kt
fun main() {

    val giants : List<String> = mutableListOf("阿部")

    giants.add("高橋") // コンパイルエラー
}
```

(´・ω・｀)「うわあああああ待って！」

## List型で型宣言してしまっている

(´・ω・｀)「これはJavaをこれまでやってきた人がハマる罠だと思う」

彡(ﾟ)(ﾟ)「確かにワイは元々Javaのエンジニアやわ」

(´・ω・｀)「結論から言うと、`giants`がList型になってるからだよ」

彡(ﾟ)(ﾟ)「なんでやねん、List型で問題ないやんけ」

(´・ω・｀)「**Java**ならね。でもKotlinだと事情が違うんだよ。先に直しちゃうと、`giants2`と`giants3`の書き方ならOKだよ」

```kotlin:giants.kt
fun main() {

    val giants  : List<String>        = mutableListOf("阿部")
    val giants2 : MutableList<String> = mutableListOf("阿部")
    val giants3                       = mutableListOf("阿部")

    giants.add("高橋") // コンパイルエラー
    giants2.add("高橋") // OK
    giants3.add("高橋") // OK
}
```

彡(ﾟ)(ﾟ)「**MutableListという型がある**んか！」

(´・ω・｀)「そうなんだ。JavaだとList型の変数に読み取り専用なList、書き込み可能なListを入れることが多いと思う。だから引っかかるんだ。」
(´・ω・｀)「これはListとMutableListの関係がわかると、すんなり理解できるよ。」


Listインターフェイスのリファレンス
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/

MutableListインターフェイスのリファレンス
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/

(´・ω・｀)「Listのリファレンスの中で、addという関数はあるか見てみてほしい。すると、**ないんだ**。Listを**継承**するMutableListのリファレンスの中で初めて登場するんだ。」

彡(ﾟ)(ﾟ)「・・・？」

(´・ω・｀)「要点を整理するとこうなるよ。」

**関係性のイメージ**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129639/8b1bbb31-cac9-210f-65f8-631d3835d605.png)

(´・ω・｀)「変数`giants`はList型だから、MutableListの親という関係になる。だからMutableListのインスタンス(**※1**)を格納できるんだ。でもList型はaddメソッドがないから呼べない。だからエラーになるんだね。」

彡(ﾟ)(ﾟ)「おー、なんとなくわかったわ」


※1 正確にはmutableListOf()メソッドで生成されるのはMutableListインターフェイス型に入ったJavaのArrayListクラスのインスタンスだよ。
ソース `kotlin-stdlib-sources.jar!/common/kotlin/collections/Collections.kt:105`

## 動くようになったかな？

彡(ﾟ)(ﾟ)「つまり、こうやな？」

```kotlin
fun main() {

    val giants  = mutableListOf("阿部")

    giants.add("高橋") // OK！
}
```

(´・ω・｀)「そうそう、それで無事実行できるようになったね！」

## おわり

良いKotlinライフを！
彡(^)(^) 「LGTM頼むで！」
(´^ω^｀)「ストックもね！」