1

最小限の作業例 (Scala 2.9.2):

object Main extends App {
  class A {
    var a=0
  }
  val b = Array.fill(2)(new A)
  b(1).a = 9
  println(b(0).a) //prints 0
  println(b(1).a) //prints 9

  val a = new A
  val c = Array.fill(2)(a)
  c(1).a = 9
  println(c(0).a) //prints 9
  println(c(1).a) //prints 9
}

関連する質問は、「インポートされたJavaクラスと同じですか?」です。関数内の配列に引数として渡されたインスタンスのコピーを入力する必要がある場合、どのように回避できますか? [同一のコピーに関しては、簡単な複製ライブラリをチェックする価値がありました。

回答に基づいて、関数呼び出しに回避策を追加するだけです。

  class A {
    var a=0
  }

  def f(a: => A) {             // "=>" added
    val b = Array.fill(2)(a)
    b(1).a=9
    println(b(0).a) //prints 0
    println(b(1).a) //prints 9
  }

  f(new A)

もう 1 つの方法は、値ではなく関数を宣言することですdef a = new A

object Main extends App {
  class A {
    var a=0
  }
  val b = Array.fill(2)(new A)
  b(1).a = 9
  println(b(0).a) //prints 0
  println(b(1).a) //prints 9

  def a = new A
  val c = Array.fill(2)(a)
  c(1).a = 9
  println(c(0).a) //prints 0
  println(c(1).a) //prints 9
}
4

3 に答える 3

7

このfillメソッドは、2 番目のパラメーターを「call-by-name」として定義されています。これは、渡されたブロックが配列内のすべてのセルに対して再評価されることを意味します。の型が単に ではなくelemisであるという定義を参照してください。=> TT

def fill[T: ClassManifest](n: Int)(elem: => T): Array[T]

したがって、最初のバージョンでは、セルごとにブロックnew Aが再評価されます。つまり、各セルは新しいAオブジェクトを取得します。2 番目のバージョンでnew Aは、 が 1 回だけ呼び出され、そのオブジェクトがすべてのセルに配置されます。

REPL で実行すると、実際にこれを確認できます。

scala> val b = Array.fill(2)(new A)
b: Array[A] = Array(A@2049bed2, A@498edd8d)    // two different objects

scala> val c = Array.fill(2)(a)
c: Array[A] = Array(A@31e0c0b6, A@31e0c0b6)    // the same object repeated
于 2012-12-05T22:42:21.573 に答える
2

fill の署名を見てみる

def fill[T: ClassManifest](n: Int)(elem: => T)

したがって、名前による呼び出し引数を取得しますnew A。つまり、配列内のセルを処理するたびに実行されます。

于 2012-12-05T22:42:23.357 に答える
1

1 つは A の 1 つのインスタンスで配列を埋め、もう 1 つは A の新しいインスタンスで配列を埋めます。

于 2012-12-05T22:41:58.307 に答える