Reputation: 247
Seems like copy doesn't preserve any state from the original instance but just uses the base class definition to make a new instance with your new value. Anyone know why it was implemented this way?
scala> case class A(){ var y = 2 }
defined class A
scala> val a = new A()
a: A = A()
scala> a.y = 9
a.y: Int = 9
scala> a.y
res9: Int = 9
scala> val b = a.copy()
b: A = A()
scala> b.y
res10: Int = 2
Upvotes: 1
Views: 284
Reputation: 1428
That is not a bug nor a mutability issue.
A case class works in a way where all its features (equals, hashcode, toString, copy, etc) are depend on its constructor parameters (some of them don't work with currying).
You will have the same problem although your variable would be a val. For example,
case class AAA() {
val field = 1
}
val instanceA = new AAA() {
override val field: Int = 5
}
println(instanceA.field)
// 5
println(instanceA.copy().field)
// 1
Your case class should be
case class A(y:Int = 2)
Upvotes: 3
Reputation: 22449
Anyone know why it was implemented this way?
This Scala-lang dialog offers good insight into why it's implemented that way. In particular, Daniel Sobral's example makes a lot of sense:
Suppose a variable should contain an unique number, such that no instances have the same number? Or suppose it points to a mutable object -- should it be shared between instances, or copied so that each instance has its own.
Upvotes: 4
Reputation: 22850
Not a direct answer to your question, but this is how you could accomplish what you want in a idiomatic Scala way.
final case class A(a: Int = 2) // if a is not provided it will fallback to the default value of 2
val a = A(a = 3) // A(3)
val b = a.copy(a = 9) // A(9) - BTW, this is the same as A(a = 9)
case classes
are intended for modeling immutable data objects, and the copy
method is provided as a shortcut when you want to create a new object which share common state with another, so you only need to define the pieces of data you want to change.
Upvotes: 2