halfwarp
halfwarp

Reputation: 1790

Scala instance variables best practice

How would one translate the following Java code to Scala?

class ClassA {
    private int field1;
    private int field2;

    public ClassA() {
        field1 = 1;
        field2 = 2;
    }
}

I can see two options:

class ClassA(val field1: Int, val field2: Int) {
   ....
}

Or

class ClassA {
   val field1: Int = 1
   val field2: Int = 2
}

What is recommended, and why?

Upvotes: 16

Views: 33898

Answers (5)

ziggystar
ziggystar

Reputation: 28680

This is the most direct translation to Scala:

class ClassA{
  private var field1 = 1
  private var field2 = 2
}

Note the usage of var instead of val. val is an immutable field, corresponding to public final in Java. Thus it cannot be changed later and providing a way to initialize such a field to the correct value for a given instance is important.

In order to decide what you want to use you should ask yourself the questions that are listed in Landei's answer.

Upvotes: 10

Landei
Landei

Reputation: 54574

There is no simple translation from Java to Scala, it depends on the context:

  • Are the variables mutable in Java? If yes (else they should be final in Java): Would it make sense to make them immutable in Scala?
  • Should the constructor stay public in Scala? Would be a factory (e.g. an apply method in the companion object) more apropriate?
  • Why are are the variables private? Do they have getters and/or setters?
  • When are the variables needed, would it make sense to make them lazy?
  • If the values are immutable and exposed, would they be useful in pattern matching? Would a case class be the right choice?
  • Could the variables be grouped (e.g. in a tuple) in order to simplify API and access?

You see, there are so many considerations. I'd suggest to learn about the possibilities of Scala, and to play around with different approaches, else you get stuck in the "Scala as better Java" trap longer than needed.

Upvotes: 20

Nicolas
Nicolas

Reputation: 24759

If you always want that field1 and field2 have the same value for each instance of the class A, I would suggest to put them in a companion module:

object A {
  private val field1 = 1
  private val field2 = 2
}

And then use them in class A:

class A {
  def complexInternalComputation = 2*A.a
}

or this way:

class A {
  import A._
  def complexInternalComputation = 2*a
}

Upvotes: 1

eivindw
eivindw

Reputation: 1959

The biggest difference between the two is that the class parameter one can be used as constructor. If you want the constructor to have no parameters, as your Java example, then you need to use the second one, plus adding the private modifier as suggested by @Debilski.

Another option would be to use default parameters in the constructor. That way the fields could be changed if needed:

class ClassA (private val field1: Int = 1, private val field2: Int = 2)

// Using defaults
val a = new ClassA

// Setting new values
val b = new ClassA(3, 4)

Upvotes: 7

Debilski
Debilski

Reputation: 67838

If you want to have private fields, why not declare them private?

class ClassA {
  private val field1: Int = 1
  private val field2: Int = 2
}

Upvotes: 5

Related Questions