Start learning free

LESSON 202 OF 414 · FUNCTIONS & CLASSES

Classes in Scala: Fields, Constructors and Methods

Lesson Read the full explanation

Scala is an object oriented programming language. Almost everything in Scala is an object, with its attributes and methods.

Class creates a user-defined data structure, which holds its own data members (attributes) and member functions (methods), which can be accessed and used by creating an instance of that class.

Classes are like a blueprint for objects outlining possible behaviors and states that every object of a certain type could have.

Classes are defined via the keyword class, like this:

// Define an empty class Employee
class Employee {

}

Objects/Instances

An Object is an instance of a Class. A class is like a blueprint while an instance is a copy of the class with actual values. It’s not an idea anymore, it’s an actual employee, like a person named "Andrew" who is 30 years old.

You can have many employees to create many different instances, but without the class as a guide, you would be lost, not knowing what information is required.

After a class is defined, we can create objects of the class by calling the class name like a function (Scala 3 does not need new), like this:

// Define an empty class Employee
class Employee {

}

// inside main function:
val employee = Employee()

Attributes/Properties

A class attribute is a Scala variable that belongs to an object of the class: each object has its own copy. Let's add some attributes to our Employee class:

class Employee {
	var name: String = ""
	var age: Int = 0
}

// inside main function:
val emp1 = Employee()
	
emp1.name = "Andrew"
println(emp1.name) // prints "Andrew"
	
val emp2 = Employee()
	
emp2.age = 40
println(emp2.age) // prints 40

We added two properties: the String name and the Int age. Then, we created two different Employee objects emp1 and emp2.

The attributes of objects can be accessed and modified using the dot operator (.), like we did above with emp1.name and emp2.age.

Class fields like name and age can be accessed and changed through each object using dot syntax.

Constructors

In real life, we want to set the attributes specific to each object when creating it. For example, an employee named Andrew of 30 years old and another one named Mary of 25 years old. Here the constructor comes to rescue.

A constructor is a special type of method (function) which is used to initialize the instance members of the class.

In Scala, constructor parameters are usually written directly in the class header.

Let's add a constructor to our Employee class:

class Employee(var name: String, var age: Int) {
}

// inside main function:
val emp1 = Employee("Andrew", 30)
	
println(emp1.name)
	
val emp2 = Employee("Mary", 25)

println(emp2.age)

// prints "Andrew" and 25 on different lines

The "this"

Every object in Scala has access to its own address through an important reference called this.

The this reference is an implicit parameter to all member functions. Therefore, inside a member function, this may be used to access and manipulate the attributes of that object, for example with this.name.

Member functions

Member functions are functions that belong to the class:

class Employee(var name: String, var age: Int) {
	
	//member functions:
	def printName(): Unit = {
		println(name) // it is not mandatory to use "this" to access an attribute
	}
		
	def printEmployee(): Unit = {
		printName()
		println(age)
	}
}

// inside main function:
val emp1 = Employee("Andrew", 30)

emp1.printEmployee() // prints "Andrew", 30
	
val emp2 = Employee("Mary", 25)

emp2.printEmployee() // prints "Mary", 25

As you can see, we access functions just like we access attributes: using the dot syntax (.).

The function call uses the attributes of the object it was called on. That's why the first printEmployee() prints "Andrew" and 30 and the second prints "Mary" and 25.


Assignment
Follow the Coding Tutorial and let's write some classes.


Hint
Look at the examples above if you get stuck.


STEP 1 OF 5
    Ctrl + Enter to check

    SCALA · FUNCTIONS & CLASSES

    Classes in Scala, explained

    What a class is

    A class is a blueprint for objects. It says what data each object holds (its fields) and what each object can do (its methods). An object, also called an instance, is one concrete thing built from that blueprint, with actual values: not the idea of an employee, but an employee named Andrew who is 30.

    The simplest class has a name and an empty body:

    class Employee {
    
    }
    

    Creating objects

    You create an instance by calling the class like a function. Scala 3 allows this without new, and new Employee still works too:

    val employee = Employee()
    val other = new Employee
    

    Each call makes a separate object with its own state.

    Fields

    A field is a variable that belongs to an object. You declare it in the class body and read or change it with the dot operator:

    class Employee {
        var name: String = ""
        var age: Int = 0
    }
    
    val emp1 = Employee()
    emp1.name = "Andrew"
    val emp2 = Employee()
    emp2.age = 40
    

    Every instance has its own copy of the fields. Setting emp1.name does not touch emp2.name, which is still the empty string. Use var for a field that can change and val for one that is set once.

    Constructors

    You usually want to give an object its values when you create it. In Scala, the constructor parameters go right in the class header:

    class Employee(var name: String, var age: Int) {
    }
    
    val emp1 = Employee("Andrew", 30)
    println(emp1.name) // Andrew
    

    The words var and val in front of a parameter do real work. With var, the parameter also becomes a public, changeable field. With val, it becomes a public read-only field. With neither, it is only a constructor parameter that the class's own methods can use, and code outside can't reach it as a field. Writing Employee("Mary", 25).name works with var or val in the header, but is a compile error without either.

    Methods

    A method is a function defined inside the class. It uses def, a name, parameters and a return type. A method that returns nothing useful has the return type Unit. Inside the class, a method can use the fields by name:

    class Employee(var name: String, var age: Int) {
        def printName(): Unit = {
            println(name)
        }
    
        def printEmployee(): Unit = {
            printName()
            println(age)
        }
    }
    
    val emp = Employee("Andrew", 30)
    emp.printEmployee() // prints Andrew, then 30
    

    You call a method with the dot, as you read a field. The call uses the fields of the object it is called on, so emp.printEmployee() prints Andrew's details, and a second employee prints hers.

    The word this

    Inside a method, this is the object the method was called on. You rarely need it, because name already means this.name. It matters when a parameter has the same name as a field:

    class Person(var name: String) {
        def rename(name: String): Unit = {
            this.name = name // field on the left, parameter on the right
        }
    }
    

    Common mistakes

    • Leaving out var or val in the constructor. The parameter is then private to the class, and outside code can't read it.
    • Assigning to a val field. If a field is declared with val, code like job.id = 2 fails to compile with Reassignment to val.
    • Forgetting that objects are references. After val j2 = j1, both names point to the same object, so changing j2.title also changes j1.title.
    • Calling a method on the class instead of an object. Methods run on an instance, so create one first.

    The lesson's exercise

    The exercise defines a class named Job with a title and a method that announces a hire, and uses it from the Solution class.

    1. Above Solution, declare class Job(var title: String). The header declares and stores the title in one line.
    2. Inside Job, define def hireMe(): Unit, a method with no parameters whose result type is Unit.
    3. In its body, print "You're hired as a " followed by title, joined with +. The field is used directly, without this.
    4. In mainFunction, create val job = Job("Software Engineer").
    5. Call job.hireMe().

    The full solution:

    class Job(var title: String) {
        def hireMe(): Unit = {
            println("You're hired as a " + title)
        }
    }
    
    class Solution {
        def mainFunction(): Unit = {
            val job = Job("Software Engineer")
            job.hireMe()
        }
    }
    

    Calling mainFunction() on a Solution prints You're hired as a Software Engineer. The variable job is a val, but that only fixes which object it refers to. The object's own var field could still be changed.

    Key takeaways

    • A class is a blueprint; each object created from it has its own field values.
    • Put the constructor parameters in the header, and add var or val to make them fields.
    • Methods are declared with def, and Unit is the return type for "nothing useful".
    • Read fields and call methods with the dot; Scala 3 lets you create objects without new.
    Keep going with ScalaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free