tags:

views:

586

answers:

4

In Scala, a class's primary constructor has no explicit body, but is defined implicitly from the class body. How, then, does one distinguish between fields and local values (i.e. values local to the constructor method)?

For example, take the following code snippet, a modified form of some sample code from "Programming in Scala":

class R(n: Int, d: Int) {
   private val g = myfunc
   val x = n / g
   val y = d / g
}

My understanding is that this will generate a class with three fields: a private "g", and public "x" and "y". However, the g value is used only for calculation of the x and y fields, and has no meaning beyond the constructor scope.

So in this (admittedly artificial) example, how do you go about defining local values for this constructor?

+16  A: 

E.g.

class R(n: Int, d: Int) {
  val (x, y) = {
    val g = myfunc
    (n/g, d/g)
  }
}
Alexander Azarov
Ah, simple really. I'm still getting my intuition around the functional concept.
skaffman
This will actually add a hidden Tuple2 field to your class.
Jorge Ortiz
This can be important. Thank you for the comment, Jorge.
Alexander Azarov
+3  A: 

There are a few ways to do that. You can declare such temporary variables inside private definitions, to be used during construction time. You can use temporary variables inside blocks which return expressions (such as in Alaz's answer). Or, finally, you can use such variables inside alternate constructors.

In a manner similar to the alternate constructors, you could also define them inside the object-companion's "apply" method.

What you can't do is declare a field to be "temporary".

Note also that any parameter received by the primary constructor is a field also. If you don't want such parameters to become fields, and don't want to expose the actual fields in a constructor, the usual solution is to make the primary constructor private, with the actual fields, and use either an alternate constructor or an object-companion's apply() as the effective "primary" constructor.

Daniel
Thanks for the clarification.
skaffman
+3  A: 

Some discussion on this topic, including Martin Odersky's comments, is here

Pavel Feldman
That's the exact example from the book that triggered my question :) I suppose it means I was paying attention...
skaffman
+1  A: 

Another option we have is to make the primary object constructor private and use a companion object's apply method as a builder. If we apply (pun is not intended) this approach to your example it will look like this:

class R private (val x: Int, val y: Int);

object R {
  def apply(n: Int, d: Int): R = {
    val g = myfunc;
    new R(n / g, d / g);
  }
}

To create an R instance instead of:

val r = new R(1, 2);

write:

val r = R(1, 2);

This is a little bit verbose, but it could be worse, I think :). Let's hope that private[this] vals will be treated as temporary variables in future releases of Scala. Martin himself hinted that.

Maxim Vladimirsky