Start learning free

LESSON 402 OF 414 · OBJECT-ORIENTED PROGRAMMING

Access Modifiers in Scala: private and protected

Lesson Read the full explanation

TL ; DR:

  • An access modifier controls who can see a member of a class. In Scala a member is public (anyone can use it) unless you mark it private (only this class).


  • Make data private so callers can't break invariants. Expose what they need through public methods (often called getters and setters):

    class Dog(private val name: String) {
        def getName(): String = {
            return name
        }
    }
    

  • Outside the class, rex.name is a compile error. Use rex.getName() instead.



Full lesson:

So far every field we wrote was public (Scala has no public keyword; it is the default). That's convenient, but leaks internals. If you later decide to validate or compute the value differently, every caller in the codebase breaks.


Encapsulation

Encapsulation is the idea that an object's data should be hidden behind methods. The class controls how it's read and written; outside code only sees the API.

class Account {
    private var balance: Double = 0.0

    def deposit(amount: Double): Unit = {
        if (amount < 0) throw new IllegalArgumentException()
        balance += amount
    }
}

The Scala access levels

(no modifier)Public — visible everywhere.
privateVisible only inside the same class.
protectedVisible inside the class and its subclasses.

For now, focus on the default (public) and private.


Your task

The Dog class's name field is now private. Add a def getName() method that returns it.

Dog's name: Rex
STEP 1 OF 2
    Ctrl + Enter to check

    SCALA · OBJECT-ORIENTED PROGRAMMING

    Access Modifiers in Scala, explained

    Why control access

    Up to now every field was visible to all code, which is convenient but leaks the internals of a class. If code everywhere reads and writes a field directly, then changing how that field works later means changing every place that touches it. An access modifier says who can see a member of a class.

    The idea behind this is encapsulation: an object's data is hidden behind methods. The class decides how the data is read and changed, and outside code sees only the methods.

    The modifiers in Scala

    ModifierWho can use the member
    (none)Everyone. Scala has no public keyword, because this is the default.
    privateOnly code inside the class itself (and its companion object).
    protectedThe class and its subclasses.

    For now, focus on the first two. Scala can also limit access to a package with a qualifier such as private[mypackage], but this lesson doesn't need it.

    A private field

    A private member can be used inside the class but not outside it:

    class Dog(private val name: String)
    

    The parameter is marked private val: it becomes a field, but only the class can see it. Outside the class, Dog("x").name doesn't compile, and the compiler explains:

    private value name can only be accessed from class Dog.
    

    The same applies to a private var declared in the class body. Assigning to it from outside is rejected in the same way.

    Getters

    If outside code needs the value, give it a public method. Methods that return a field are called getters:

    class Dog(private val name: String) {
        def getName(): String = {
            return name
        }
    }
    

    Inside the class, name is accessible directly, so getName can return it. Callers use rex.getName() and never touch the field. Scala would also accept the bare expression name as the method's body, without return, since the last expression is the result.

    A getter is also a place to add rules. A class can hide a counter and offer only a controlled way to change it:

    class Dog(private val name: String) {
        private var energy: Int = 10
        def run(): Unit = { if (energy > 0) energy -= 1 }
        def getEnergy: Int = energy
    }
    

    Outside code can call run() and read getEnergy, but cannot set energy to a negative number. After one call of run() on a new dog, getEnergy is 9.

    Because private works per class, not per object, a dog's method can read another dog's private field: inside Dog, a method taking o: Dog may use o.name. That is how a method like same(o: Dog): Boolean = name == o.name works.

    protected

    A protected member is hidden from the outside but available to subclasses. In a class Dog with protected def secret(): String = "s", a subclass such as Puppy can call secret(), while Dog().secret() from unrelated code is rejected with method secret cannot be accessed as a member of Dog. Subclasses are covered in the next lessons.

    The exercise

    The starter code gives Dog a private val name, and mainFunction calls rex.getName(). Add the getter:

    class Dog(private val name: String) {
        def getName(): String = {
            return name
        }
    }
    
    class Solution {
        def mainFunction(): Unit = {
            val rex = Dog("Rex")
            println("Dog's name: " + rex.getName())
        }
    }
    

    The output is Dog's name: Rex.

    Common mistakes

    • Reading the private field from outside. rex.name in mainFunction doesn't compile. Use rex.getName().
    • Writing public. Scala has no such keyword. Leave the modifier out.
    • Procedure syntax. def getName() { return name } without the : String = part doesn't compile in Scala 3, which reports '=' expected, but '{' found.
    • Using val when a var is needed. A private val never changes. Use a private var for state that methods change.

    Key takeaways

    • Members are public by default, and private hides them from code outside the class.
    • Keep data private and offer public methods to read or change it.
    • protected also lets subclasses use a member.
    • A getter is an ordinary method that returns a private field.
    Keep going with ScalaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free