Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala object cloning (copying) without value re-valuation

Tags:

clone

copy

scala

I have big object:

case class BigObject(val str: String, val number: Int) {
val someVal = ...
val someVal2 = ...
    }

I'd like to copy this object without re-valuation of values. Is it possible? Right now I'm using this approach:

val newBigObject = oldBigObject.copy(str = newStr)

As I see from the logs/debugger, "someVal" and "someVal2" are re-valuated. Is it possible to avoid it? As my BigObject is really big and value re-valuation takes some time, but performance is really important for me.

Thanks for your answers!

like image 314
psisoyev Avatar asked Mar 22 '13 10:03

psisoyev


1 Answers

Here's a way:

Make the someVal and someVal2 fields which are also passed to the constructor and pull out the initialization logic for those fields in the companion object.

In your case:

class BigObject private(val str: String,
                        val number: Int,
                        val someVal: SomeType,
                        val someVal2: SomeType) {

   def copy(newStr: String = str, newNumber: Int = number) = {
     new BigObject(newStr, newNumber, someVal, someVal2)
   }
}

object BigObject {

  def apply(str: String, number: Int): BigObject = {
    val someVal = initialize() //your initialization logic here
    val someVal2 = initialize2()
    new BigObject(str, number, someVal, someVal2)
  }

}

Now, you can copy without re-evaling the inner fields:

val bigObj = BigObject("hello", 42)
val anotherBigObj = bigObj.copy(newStr = "anotherStr")

Alternatively, if you don't like companion objects, you can make two constructors. The primary one includes all the fields (also the non visible ones) and will be private. The public one will have only the two visible parameters:

class BigObject private(val str: String,
                        val number: Int,
                        val someVal: Any,
                        val someVal2: Any) {

  def this(str: String, number: Int) = this(str, number, initializeVal, initializeVal2)

  def copy(newStr: String = str, newNumber: Int = number) = {
    new BigObject(newStr, newNumber, someVal, someVal2)
  }

}

Usage:

val bigObj = new BigObject("hello", 42)
val anotherBigObj = bigObj.copy(newStr = "anotherStr")
like image 196
Marius Danila Avatar answered Oct 17 '22 21:10

Marius Danila