Scala provides a more granular access control if compared to Java. This post describes and shows how to implement each of the Scala access modifiers.
Scala has only two explicit access modifiers: private
and protected
, besides the implicit no modifier that defaults to public access.
However, we can qualify these modifiers to give them a finer-grained access control level.
The access levels from the most-restrictive to the less-restrictive are the following:
Access level | Access modifier |
Object-private | private[this] |
Private | private |
Protected | protected |
Package-specific | private[your.package] |
Public | no modifier |
This is the most restrictive access level, declared by qualifying the member as private[this]
. Object-private members can only be called within the same instance:
class Bar { private[this] def doSomethingVeryRestrictive(): Unit = { println("Object-private method.") } def callVeryRestrictiveMethod(): Unit = { doSomethingVeryRestrictive() } def cannotCallFromOtherObject(otherBar: Bar): Unit = { otherBar.doSomethingVeryRestrictive() // Doesn't compile } }
Declared with the private
keyword. Similar to Java, Private members can be called only by the same class:
package com.bgasparotto.learningscala.accessmodifier class Baz { private def doSomethingPrivate(): Unit = { println("Private method.") } def callPrivateMethod(otherBaz: Baz): Unit = { otherBaz.doSomethingPrivate() } } class NotBaz { def cannotCallPrivateMethodFromOtherClass(baz: Baz): Unit = { baz.doSomethingPrivate() // Doesn't compile } }
Declared with the protected
keyword. Unlike Java, protected members can be accessed only by subclasses, but not from other classes in the same package:
package com.bgasparotto.learningscala.accessmodifier // Declares a protected method class Boo { protected def doSomethingProtected(): Unit = { println("Protected method.") } }
package com.bgasparotto.learningscala.accessmodifier.other import com.bgasparotto.learningscala.accessmodifier.Boo // Subclass of Boo (can be either on the same or different package) class SubBoo extends Boo { def callProtectedMethodHere(boo: Boo): Unit = { doSomethingProtected() } def callProtectedMethodThere(boo: Boo): Unit = { boo.doSomethingProtected() } }
package com.bgasparotto.learningscala.accessmodifier // Doesn't work: resides on the same package but it is not a subclass class NotSubBoo { def cannotCallProtectedMethodSamePackage(boo: Boo): Unit = { boo.doSomethingProtected() // Doesn't compile } }
Declared using a combination of the keyword private
and the package level starting from the current location and optionally stepping-up the hierarchy.
In other words, the package-specific access level defines whether your type will be available only to members of the current package and its sub-packages, or to members of an upper-level package including its sub-packages as well:
package com.bgasparotto.learningscala.accessmodifier.other class Fuz { private[accessmodifier] def doSomethingAbroad(): Unit = { println("Package-specific to packages [accessmodifier] and any of its sub-packages.") } private[other] def doSomethingFromPackage(): Unit = { println("Package-private method (specific to [other])") } }
The class Foz
from the same package have access to all Fuz
methods:
package com.bgasparotto.learningscala.accessmodifier.other class Foz { def callPackagePrivateMethod(fuz: Fuz): Unit = { fuz.doSomethingAbroad() } def callBroaderPackageSpecificMethod(fuz: Fuz): Unit = { fuz.doSomethingFromPackage() } }
The class AnotherFuz
can access only the method restricted to the accessmodifier
package and its sub-packages, which this case is defined in accessmodifier.another
:
package com.bgasparotto.learningscala.accessmodifier.another import com.bgasparotto.learningscala.accessmodifier.other.Fuz class AnotherFuz { def callAccessibleMethod(fuz: Fuz): Unit = { fuz.doSomethingAbroad() } def cannotCallTheOtherOne(fuz: Fuz): Unit = { fuz.doSomethingFromPackage() // Doesn't compile } }
And as expected, Faz
which resides in an even higher package can’t access any methods:
package com.bgasparotto.learningscala import com.bgasparotto.learningscala.accessmodifier.other.Fuz class Faz { def callAccessibleMethod(fuz: Fuz): Unit = { fuz.doSomethingAbroad() // Doesn't compile } def cannotCallTheOtherOne(fuz: Fuz): Unit = { fuz.doSomethingFromPackage() // Doesn't compile either } }
Finally, when no access modifier is declared, the access level is set to public by default.
/* Public class given no access modifier was declared. */class Foo { def doSomething(): Unit = { println("Public method.") } }
Unlike in Java, the keyword public is not reserved in Scala.
Hope it helps!
This guide will show you how to create a Python function decorator with a few…
This guide will show you how to fix the error Got permission denied while trying…
This guide will show you how to create a Python virtual environment on Intellij IDEA…
This tutorial will quickly show you how to to find and kill processes on Linux,…
This guide shows a possible solution for Python error Relocation R_X86_64_PC32 against symbol can not…
I condensed below a cheat sheet of Kubernetes useful commands. I will keep updating this…