Reputation: 5300
Take the following code:
class A(val i: Int)
case class B(str: String) extends A(1)
val b = B("test")
In my scenario I am restricted by the definition of B which cannot be changed. I also wish to avoid reconstructing B as I have many such objects with a lot more attributes than in this example.
Is there any way I can create a new copy of b (using reflection or otherwise) with a new value for i?
Something that would be the equivalent of:
val b2 = b.copy(i = 2)
NOTE: The question is can it be done? Not what the best programming practice is.
Upvotes: 0
Views: 96
Reputation: 40510
You can do it using reflection with something like this:
val b = B("foo")
val c = b.copy()
println(b.i) // prints 1
val field = classOf[A].getDeclaredFields.head
field.setAccessible(true)
field.setInt(c, 2)
println(c.i) // prints 2
But beware, this is not just "bad programming practice", but rather complete breakage of the contract.
Your declaration case class B(s: Sting) extends A(1)
promises that all instances of B
will always have i
equal to 1, which is a lie.
Not to mention, fun facts like b == c
being true
or c.copy.i
being 1 etc.
Don't do this.
Upvotes: 1
Reputation: 27421
You can do this:
val b2 = new B(b.str) { override val i = 2 }
The downside is that you have to re-construct B
from the parameters which may be cumbersome if there are a lot of them.
Upvotes: 0
Reputation: 23788
Not if you define B
that way. But this code works for me:
class A(val i: Int)
case class B(str: String, override val i:Int=1) extends A(i)
val b = B("test")
val b2 = b.copy(i = 2)
P.S. well technically you can just copy with no modifications and then edit i
using reflection but this is not a great idea IMHO.
Upvotes: 0