How to set uninitialized var fields (field types) in Scala

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is a short recipe, Recipe 4.9, “How to set uninitialize var field types in Scala.”

Problem

You want to set the type for an uninitialized var field in a Scala class, so you begin to write code like this:

var x =

and then wonder how to finish writing the expression.

Solution

In general, define the field as an Option. For certain types, such as String and numeric fields, you can specify default initial values.

For instance, imagine that you’re starting a social network, and to encourage people to sign up, you only ask for a username and password during the registration process. Therefore, you define username and password as fields in your class constructor:

case class Person(var username: String, var password: String) ...

However, later on, you’ll also want to get other information from users, including their age, first name, last name, and address. Declaring those first three var fields is simple:

var age = 0
var firstName = ""
var lastName = ""

But what do you do when you get to the address?

The solution is to define the address field as an Option, as shown here:

case class Person(var username: String, var password: String) {
    var age = 0
    var firstName = ""
    var lastName = ""
    var address = None: Option[Address]
}

case class Address(city: String, state: String, zip: String)

Later, when a user provides an address, you can assign it using a Some[Address], like this:

val p = Person("alvinalexander", "secret")
p.address = Some(Address("Talkeetna", "AK", "99676"))

When you need to access the address field, there are a variety of approaches you can use, and these are discussed in detail in Recipe 20.6. As one example, if you want to print the fields of an Address, calling foreach on the address field works well:

p.address.foreach { a =>
    println(a.city)
    println(a.state)
    println(a.zip)
}

If the field hasn’t been assigned, address is a None, and calling foreach on it does no harm, the loop is just skipped over. If the address field is assigned, it will be a Some[Address], so the foreach loop will be entered and the data printed.

Discussion

In a related situation, setting the type on numeric var fields can occasionally be interesting. For instance, it’s easy to create an Int or Double field:

var i = 0    // Int
var d = 0.0  // Double

In those cases, the compiler automatically defaults to the desired types, but what if you want a different numeric type? This approach lets you give each field the proper type, and a default value:

var b: Byte  = 0
var c: Char  = 0
var f: Float = 0
var l: Long  = 0
var s: Short = 0

See Also