Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

constructors in scala (primary/auxiliary/default primary)

A quite simple exercise from Cay Horstmann's book « Scala for the impatient » keeps puzzling me. It's about primary,auxiliary and default primary constructors :

ex 5.10 : Consider the class

class Employee(val name: String, var salary: Double) {
  def this() { this("John Q. Public", 0.0) }
}

Rewrite it to use explicit fields and a default primary constructor.

I'm not sure about I am supposed to do. Could some of you propose a solution ?

However, trying to solve this exercise may have made me aware of something I hadn't noticed before about primary constructor and val fields (as you can see, I'm not quite sure) :

Am I right if I say that a val field (as name in the Employee class above) may only be initialized through the primary constructor and not by an auxiliary one ? In the latter case it would be considered by the compiler as a reassignment to a val field causing an error.

At first I thought to val fields as a rough equivalent to final fields in java expecting that it would be legal to assign them for the first time in any constructor but it seems I was wrong.

I am not quite satisfied with what may only be a wild guess so I would appreciate if someone could give me more accurate information about that point.

like image 812
Jerome ROBERT Avatar asked May 03 '12 06:05

Jerome ROBERT


2 Answers

From "Programming in Scala, 2nd edition" paragraph 6.7:

In Scala, every auxiliary constructor must invoke another constructor of the same class as its first action. The net effect of this rule is that every constructor invocation in Scala will end up eventually calling the primary constructor of the class. The primary constructor is thus the single point of entry of a class.

So all data for initialization of val must be in primary constructor.

Your class with explicit fields may be something like:

class Employee(n: String = "John Q. Public", s: Double = 0.0) {
  val name = n
  var salary = s
}

or without default parameter values:

class Employee(n: String, s: Double) {
  def this() = this("John Q. Public", 0.0)
  val name = n
  var salary = s
}
like image 144
Sergey Passichenko Avatar answered Oct 25 '22 17:10

Sergey Passichenko


Actually, what I had in mind is a version with a no-argument primary constructor, like this:

class Employee {
  private var _name = "John Q. Public"
  var salary = 0.0
  def this(n: String, s: Double) { this(); _name = n; salary = s; }
  def name = _name      
}

Clearly, this is inferior to defining the fields in the primary constructor, which is the point that I wanted to make.

like image 27
cayhorstmann Avatar answered Oct 25 '22 16:10

cayhorstmann