web-dev-qa-db-ja.com

Valはkotlinのfunのローカル変数にコンパイル時エラーを再割り当てできません

ここで楽しいスワップでは、a1の値をb1で変更しようとしていますが、valはコンパイル時エラーを再割り当てできないことを示しています。このように変更できない場合、どのように行うことができます。

fun swap(a1: String, b1: String) {
   val temp = a1
   a1 = b1
   b1 = temp
}

注:これは、Javaでできるようにローカル変数を再割り当てできない理由を知るための単なるサンプルです

18
YLS

Kotlinでは、valは最終的な読み取り専用の参照を宣言します。これは、コンパイラエラーがあなたに伝えていることです。

Valは再割り当てできません

valに値を割り当てた後は、変更できません。再割り当てできるようにするには、varとして宣言する必要があります

Kotlinメソッドでは、パラメーターは暗黙的にfinal valとして宣言されるため、Javaでできるように再割り当てすることはできません。

しかし、コードのコアエラーは、メソッドパラメーターを交換しようとしていることです。メソッドパラメーターは参照ではなく値で渡されるため、Kotlinでは達成したいことは不可能です(Javaでも不可能です)。メソッド呼び出し内でパラメーターを再割り当てしても、メソッドに渡される元の変数は変更されません。

29

ここには2つの誤解があります。

まず、Kotlinではすべてのパラメーターはfinalであり、これは変更できません。 Java a final参照は変更できないため、finalまたはval参照を再割り当てしようとするとエラーが発生します。

次に、文字列への参照のコピーがあるため、スワップ関数は呼び出し元の元の参照に影響を与えません。スワップ関数は、Javaでも動作しません。

たとえば、コードを呼び出しても何も起こりません。

val s1 = "howdy"
val s2 = "goodbye"
swap(s1,s2)   // Java or Kotlin, doesn't matter
println(s1)
println(s2)

// output:
// howdy
// goodbye

そして、それをリテラルまたは式で確実に呼び出しても何も起こりません。

swap("happy","day")  // what references is it supposed to be swapping?

呼び出し元と同じ参照を保持しているオブジェクト内のコンテンツのみを交換できます。スワップルーチンを作成するには、次のようにします。

data class MutablePair(var one: String, var two: String)

fun swap(pair: MutablePair) {  // not thread safe       
   val temp = pair.one
   pair.one = pair.two
   pair.two = temp
}

あなたはどちらを呼び出すことができます:

val stringies = MutablePair("howdy", "goodbye")
println("${stringies.one} ${stringies.two}")
swap(MutablePair()
println("${stringies.one} ${stringies.two}")

// output:
// howdy goodbye
// goodbye howdy
5
Jayson Minard

関数パラメーターの値を変更することはできません。代わりに、スワップされた値の新しい変数を作成します。

fun swap(a1: String, b1: String) {
    val a1Swapped = b1
    val b1Swapped = a1
}
0
gildor