5.7 The Primary Constructor
In Scala, every class has a primary constructor. The primary constructor is not defined with a this method. Instead, it is interwoven with the class definition.
The parameters of the primary constructor are placed immediately after the class name.
The primary constructor executes all statements in the class definition. For example, in the following class
class Person(val name: String, val age: Int) { // Parameters of primary constructor in (...) ... }
Parameters of the primary constructor turn into fields that are initialized with the construction parameters. In our example, name and age become fields of the Person class. A constructor call such as new Person("Fred", 42) sets the name and age fields.
Half a line of Scala is the equivalent of seven lines of Java:
public class Person { // This is Java private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String name() { return this.name; } public int age() { return this.age; } ... }
class Person(val name: String, val age: Int) { println("Just constructed another person") def description = s"$name is $age years old" }
the println statement is a part of the primary constructor. It is executed whenever an object is constructed.
This is useful when you need to configure a field during construction. For example:
class MyProg { private val props = new Properties props.load(new FileReader("myprog.properties")) // The statement above is a part of the primary constructor ... }
Primary constructor parameters can have any of the forms in Table 5–1. For example,
class Person(val name: String, private var age: Int)
declares and initializes fields
val name: String
private var age: Int
Construction parameters can also be regular method parameters, without val or var. How these parameters are processed depends on their usage inside the class.
If a parameter without val or var is used inside at least one method, it becomes a field. For example,
class Person(name: String, age: Int) { def description = s"$name is $age years old" }
declares and initializes immutable fields name and age that are object-private.
Such a field is the equivalent of a private[this] val field (see Section 5.4, “Object-Private Fields,” on page 60).
Otherwise, the parameter is not saved as a field. It’s just a regular parameter that can be accessed in the code of the primary constructor. (Strictly speaking, this is an implementation-specific optimization.)
Table 5–2 summarizes the fields and methods that are generated for different kinds of primary constructor parameters.
Table 5–2 Fields and Methods Generated for Primary Constructor Parameters
Primary Constructor Parameter |
Generated Field/Methods |
name: String |
object-private field, or no field if no method uses name |
private val/var name: String |
private field, private getter/setter |
val/var name: String |
private field, public getter/setter |
@BeanProperty val/var name: String |
private field, public Scala and JavaBeans getters/setters |
If you find the primary constructor notation confusing, you don’t need to use it. Just provide one or more auxiliary constructors in the usual way, but remember to call this() if you don’t chain to another auxiliary constructor.
However, many programmers like the concise syntax. Martin Odersky suggests to think about it this way: In Scala, classes take parameters, just like methods do.