Skip to content

Scala Access Modifiers

Scala controls visibility of class, trait, and object members using access modifiers: private, protected, and the default (public). Scala also supports scoped modifiers like private[package] or protected[this] for finer-grained control.

If no access modifier is specified, the member is public. Public members are accessible from anywhere the containing class/object/package is accessible.

class PublicExample {
val publicField = 10
def publicMethod(): String = "Accessible everywhere"
}
val ex = new PublicExample()
ex.publicField // OK
ex.publicMethod() // OK

A member marked private is visible only within the lexical scope of the class or object that contains the member definition, including nested classes or objects.

class Outer {
class Inner {
private def secret() = println("Inner secret")
def revealSecret() = secret() // OK: Access within Inner
class InnerMost {
// secret() // Error: Not accessible from InnerMost (though nested, different class scope)
// Correction: Scala allows access from *enclosing* class scope
def accessOuterInnerSecret() = secret() // OK: InnerMost is inside Inner
}
}
private val outerSecret = "Outer secret"
// (new Inner).secret() // Error: secret is private to Inner, cannot access from Outer
val innerInstance = new Inner()
innerInstance.revealSecret() // OK: Calling public method of Inner
}

Note: Unlike Java, an outer class cannot access private members of its inner class directly (unless using scoped modifiers).

A member marked protected is accessible only from subclasses of the class in which the member is defined. Unlike Java, protected in Scala does not grant package access by default.

package scopeA {
class Superclass {
protected def protectedMethod() = println("Superclass protected method")
}
class Subclass extends Superclass {
def accessProtected() = protectedMethod() // OK: Subclass accessing protected member
}
class Other {
val sup = new Superclass()
// sup.protectedMethod() // Error: protectedMethod not accessible from Other (not a subclass)
}
}
package scopeB {
// import scopeA._ // Needed if in different files
class AnotherSubclass extends scopeA.Superclass {
def accessProtectedToo() = protectedMethod() // OK: Subclass in different package
}
}

Scoped Access Modifiers (Access Qualifiers):

Section titled “Scoped Access Modifiers (Access Qualifiers):”

Scala allows refining the scope of private and protected using qualifiers in square brackets []. private[X] or protected[X] means the member is accessible up to the enclosing package X, class X, or singleton object X.

Object-private. The member is accessible only from within the same object instance. Even other instances of the same class cannot access it. This is the most restrictive modifier.

class Counter {
private[this] var count = 0 // Only accessible via 'this'
def increment() = { count += 1 }
def current = count
def isLess(other: Counter): Boolean = {
// count < other.count // Error: Cannot access private[this] 'count' of 'other' instance
this.count < other.current // OK: Accessing via public method 'current'
}
}

Makes the member accessible to any code within the specified scope.

package vehicle {
class Engine {
// Visible to any code within the 'vehicle' package
private[vehicle] def start() = println("Engine starting...")
}
class Car {
val engine = new Engine()
def turnOn() = {
engine.start() // OK: Car is in package 'vehicle'
}
}
package parts {
class SparkPlug {
// Cannot access engine.start() here, as parts is nested deeper than 'vehicle'
}
}
}
package navigation {
// Cannot access engine.start() here, different package
}

Similar to private[X], but access is restricted to subclasses within the scope X.

These modifiers provide fine-grained control over encapsulation, allowing precise definition of visibility boundaries.