【Kotlin】byと=の違いってなに?
はじめに
自分はまだKotlin歴が浅く(1.5ヶ月弱)でアプリ開発未経験から一気にインターンまでやっていてインプットの日々を送っています。
理解が間違っているかもしれませんが、温かい目で見守って下さい。
本題
by vs =
僕個人的にはずっとこれに苦しんできました。もともとPythonを使っていたため、変数にプロパティを委譲するなんて考えたことがなく(=で全部何とかなる)ので。
こんなところで詰まりました。
val testInput by mutableStateOf("")
testInput = "hoge"
val testInput by mutableStateOf("")
testInput.value = "hoge"
では何故これらが弾かれてしまうのでしょうか、、、
なんやねん、プロパティ委譲て
プロパティ委譲、別名Delegateと言います。イメージ的にはカービィが相手食ってそいつの能力を使えるようになる的な(間違っていたらごめんなさい)
コード的には以下のようになる。
import kotlin.reflect.KProperty
// 委譲先のクラス
class SimpleDelegate(private val initialValue: String) : ReadOnlyProperty<Any?, String> {
private var value = initialValue
// プロパティの値を取得
override fun getValue(thisRef: Any?, property: KProperty<*>): String {
println("Getting value for ${property.name}: $value")
return value
}
}
class Example {
// SimpleDelegateを使ってnameプロパティを委譲
val name: String by SimpleDelegate("Kotlin")
}
fun main() {
val example = Example()
println(example.name) // 委譲されたプロパティを取得
println(example.name) // 2回目の取得
}
今回はReadOnlyPropertyのところでStringの型を定義しているので、val name:String
にしている。
こんな感じでbyを使うと、委譲先のクラスのプロパティを使うことができてすごい便利(.valueとか使ってアクセスすることなく、直接アクセスすることができる。)
なぜさっきうまくいかなかったのか
NG1でダメだった理由はつまりval
を使ってしまったからだ。
プロパティ委譲を使った変数はvalueに直接アクセスすることができると言ったが、valは不変の変数であることを忘れてはいけない。
よって以下の例で改善することができる。
var testInput by mutableStateOf("")
private set
testInput = "hoge"
varだと可変の変数であるため、変更可能になってしまうのだ。そして、private set
にすることで、クラス内部のみで変更可能にすることができる。
NG2でダメだった理由は.value
を使ってしまったからだ。
プロパティ委譲をしてしまった以上、直接アクセスすることしかできないため、もし.valueでアクセスしたい場合は以下のように修正する必要がある。
val testInput = mutableStateOf("")
testInput.value = "hoge"
これだとtestInput内のmutableStateOfを変更していることになり、エラーが出ない。(さっきはtestInputそのものがmutableStateOfになってしまっている、という感覚)
参考文献
ChatGPTさん、議論に付き合ってくれてありがとう。
Discussion