What a field is
An empty Dog class is an empty shell, and every Dog object is identical to every other one. A field attaches data to the objects of a class. It is a variable that belongs to the class, and each object gets its own copy of every field.
Declaring fields
Inside the class body, a field is declared like any other variable, with var or val, a name, a type and an initial value:
class Dog {
var name: String = ""
var age: Int = 0
}
var name: String = ""declares a field callednameof typeString, starting out as an empty string.var age: Int = 0declares anIntfield that starts at 0.- There is no
publickeyword. In Scala, members are public unless you mark them otherwise, so code outside the class can read and write these fields. Theprivatemodifier comes in a later lesson.
Reading and writing fields
The dot operator reaches a field of one particular object:
val dog = Dog()
dog.name = "Rex"
dog.age = 4
println(dog.name)
The last line prints Rex. Notice that dog is a val, yet its fields change. The val means that the name dog always refers to the same object. It says nothing about whether that object's var fields can change.
Each object has its own slot for every field, so two dogs can have different names:
val other = Dog()
other.name = "Luna"
println(dog.name + " " + other.name)
This prints Rex Luna. But two names for one object share its fields. After val alias = dog and alias.age = 9, dog.age is 9 too, because there is only one object.
var versus val for fields
- A
varfield can be reassigned at any time. - A
valfield is set once and then fixed. Inclass Dog { val legs: Int = 4 }, the linedog.legs = 3doesn't compile, and the error isReassignment to val legs.
Choose val for data that must never change and var for data that does. The lesson's fields change, so they use var.
Initial values
A Scala field always needs an initial value. A declaration such as var age: Int inside a class body doesn't compile: the compiler reports that the class needs to be abstract, since the variable is not defined, and notes that variables need to be initialized. This is why the lesson's step gives each field a default value, so that a new Dog starts with placeholder data.
Natural placeholders are 0 for numbers, false for a Boolean and an empty string for text. Some people also use null for a reference type, as in var tag: String = null, but then reading the field gives null, and calling a method on it would fail at run time. Prefer a real value, or an Option when a value may be missing.
If you do need a field that is filled in later, scala.compiletime.uninitialized gives it the JVM's default (0 for numbers, null for references), but a visible placeholder is clearer.
The exercise
Give Dog two var fields, name and age, and set them from mainFunction:
class Dog {
var name: String = ""
var age: Int = 0
}
class Solution {
def mainFunction(): Unit = {
val dog = Dog()
dog.name = "Rex"
dog.age = 4
println(s"${dog.name} is ${dog.age} years old")
}
}
The output is Rex is 4 years old.
The s in front of the string turns on interpolation. Inside it, ${...} evaluates any expression, here the field accesses dog.name and dog.age. Writing a plain $name only works for a simple name, not for an expression with a dot, so braces are needed.
Common mistakes
- Leaving out the initial value.
var name: Stringin a class body is rejected. - Using
valfor a field you plan to change. The assignment inmainFunctionthen fails to compile. - Putting a type before the name.
String nameis not Scala. The name comes first, then:and the type. - Writing
public. It is not a Scala keyword and the compiler reports an error. - Mixing up
Dog.nameanddog.name. Fields belong to objects, so you always write them after an object such asdog, not after the class name.
Key takeaways
- A field is a variable inside a class, and each object has its own copy.
- Declare it with
varorval, a type and an initial value. - Read and write it with the dot operator.
- Members are public by default in Scala.
