Minimal Working Example (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
}
A related question is “Is it the same with imported Java classes?”
How can I workaround, if I need to fill an Array inside a function with copies of an instance passed as argument?
[Regarding identical copies, it was worth to me to check out the easy cloning library.
Just adding the workaround to a function call, based on answers:
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)
Another way is to declare a function, not a value 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
}
The
fillmethod is defined with it’s second parameter as “call-by-name”. This means that the passed-in block is re-evaluated for every cell in the Array. See in the definition that the type ofelemis=> T, not simplyT:So in your first version, the block
new Ais re-evaluated for each cell, meaning that each cell gets a freshAobject. In the second version,new Ais called only once, and that object is placed into every cell.You can actually see this if you run on the REPL: