3

I am porting my java code to scala, and have a constructor that does quite some stuff:

  1. open hibernate session to load data
  2. do loading (now the session is kept open! I need lazy loading further on)
  3. perform some operations on loaded data and put in containers
  4. tie containers with their consumers
  5. ..blah blah
  6. close session

The constructor produces quite a number (~20) of object members, that are final (val in scala). Their creation is not independent, also note that session. Obviously I don't want the session and other temporary stuff to become constructed instance members. How do I do that in scala?

Similar questions have been already asked before:

Answers given in previous topics suggest either returning a tuple of ~20 fields from initialization method, or creating a private constructor that takes those ~20 values as parameters from companion object apply method. Either seems pig ugly to me.

So far the most sensible approach seems to declare those fields as vars, not vals, and reassign them in some initialization method, which also kinda smells.

Community
  • 1
  • 1
enlait
  • 607
  • 1
  • 6
  • 19

2 Answers2

2

I have a technically correct solution, but it might not be what you wanted, because it introduces a lot of verbocity

trait Example {
  val a1 : Int
  val a2 : Int
  val a3 : Int
  val a4 : Int
  val a5 : Int
  val a6 : Int
}
object Example {
  def apply(seed : Int) : Example = {
    val x1 = seed + 1
    val x2 = x1 * 2
    val x3 = x2 / 3
    val x4 = x3 + x1
    val x5 = x4 * x2
    val x6 = x5 - x4
    new Example {
      override val a1 = x1
      override val a2 = x2
      override val a3 = x3
      override val a4 = x4
      override val a5 = x5
      override val a6 = x6
    }
  }
}

So there is no constructor neither initializing method that takes many of variables, but they are passed via trait extending

ayvango
  • 5,867
  • 3
  • 34
  • 73
  • Do I get it right this is equivivalent to java code: `interface Example { int a1(); int a2(); } class ExampleFactory { public Example makeInstance(int seed){ final int x1 = seed + 1; final int x2 = x1 * 2; return new Example() { int a1() {return x1;} int a2() {return x2;} } } }` PS stupid comment formatting – enlait May 08 '14 at 09:55
  • I came to scala without previous experience in java, but your code seems to be rough equivivalent – ayvango May 08 '14 at 10:01
  • I think this is in fact quite concise solution, very readable and easy to understand. – enlait May 08 '14 at 10:08
0

Another (complex) way would be something like this:

import Person.getParams

class Person private (t: (Int, String, String)) {
    val a = t._1
    val b = t._2
    val c = t._3

  def this(filename: String) {
    this(getParams(filename))
  }
}

object Person {
  def getParams(filename: String): (Int, String, String) {
     // do some logic with filename which results in the relevant tuple
     // return the tuple
  }
}

Of course this is limited to 22 parameters so if you need more you would need an actual class...

Assaf Mendelson
  • 12,701
  • 5
  • 47
  • 56