KotlinのMutableとImmutable【初学者向け】
結論から言うと
- できる限り
val
を使うこと - 外部に公開するデータはImmutableにする
- 内部のみで扱うならばMutableでも可
var
とMutableの組み合わせは最悪
MutableとImmutableって何
簡単に言うと、Mutableは変更を許し、Immutableは変更を許さないものを指す。
Kotlinでは変数定義でこれをそれぞれvar
とval
で表すことができる。
変数定義
val
… 読み込み専用の変数。Immutableな変数。var
… 読み書きできる変数。Mutableな変数。
val data1 = 100
var data2 = 100
data1 = 200 // できない
data2 = 200 // できる
変数はできるだけvalで定義し、不正な、あるいは思わぬ変更を考慮する必要は無くしたほうが良い。
ちなみにval
はvalue (値)、var
はvariable (変数)の略。
リストなど
Kotlinで標準利用できる、List
やMap
は明示的にMutableとImutableが分かれている。
val list1 = listOf(1, 2, 3)
val list2 = mutableListOf(1, 2, 3)
list1.add(4) // できない
list2.add(4) // できる
また、MutableList
はList
を親クラスに持つので、MutableList
はList
に特に明示的なキャストを書かずとも、アップキャストができる。
val list3: List<Int> = list2
ただし、中身 (参照) は一緒なのでlist2
を変更すればlist3
の中身も変更される。
この性質は意味ないように思えるが…
MutableとImmutableの使い分け
基本的に、publicなプロパティはImmutableであるべきである。
なぜなら、外部から容易に変更ができてしまい、不正な利用によって中身がめちゃくちゃにされてしまう恐れがあるから。
内部 (private) なプロパティであればMutbleで問題ない。
でも、「変更が必要なデータを外部に公開したい時」がある。
例えばLiveDataなどはそのような状況がよくある。
そう言った時は、以下のように2つLiveDataを用意して、Mutable側のデータを外部に公開すれば良い。
// 内部で変更されるデータ
private val _data = MutableLiveData<Int>()
// 外部公開用のデータ
val data: LiveData<Int> = _data
一番最悪なパターン
Mutableでvar定義されたオブジェクト、さらにpublicならばそれは最悪な定義方法。
var list = mutableListOf(1, 2, 3)
何かしら特定の理由がない限り、これはやらないようにする。
リストの中身が外部から変更される恐れがあるだけでなく、リスト丸ごと別なものに変えられてしまう恐れがある。
まとめ
- できる限り
val
を使うこと - 外部に公開するデータはImmutableにする
- 内部のみで扱うならばMutableでも可
var
とMutableの組み合わせは最悪