Scala Access Modifiers
In Scala, access modifiers are used to control the visibility and access permissions of classes, objects, traits, and their members (such as fields and methods).
Scala access modifiers are basically the same as Java's: private, protected, and public.
If no access modifier is specified, by default, Scala's access level is public.
The private qualifier in Scala is stricter than in Java. In the case of nested classes, the outer class cannot even access the private members of the nested class.
Private members
Members marked with the private keyword are visible only inside the class or object that contains the member definition. The same rule also applies to inner classes.
Example
class Inner{
private def f(){
println("f")
}
class InnerMost{
f() // Correct
}
}
(new Inner).f() // Error
}
(new Inner).f( )The access is illegal becausefit is declared private in Inner, and the access is not within class Inner.
But accessing it in InnerMostfis fine, because this access is within the Inner class.
Java allows both accesses because it allows outer classes to access the private members of inner classes.
Protected members
In Scala, access to protected members is stricter than in Java. It only allows protected members to be accessed in subclasses of the class where the member is defined. In Java, members modified with the protected keyword can be accessed by subclasses of the class that defines the member, as well as by other classes in the same package.
Example
class Super {
protected def f() {println("f")}
}
class Sub extends Super {
f()
}
class Other {
(new Super).f() // Error
}
}
In the above example, Sub class's access to f is fine because f is declared protected in Super, and Sub is a subclass of Super. In contrast, Other's access to f is not allowed because Other does not inherit from Super. The latter is also allowed in Java because Other and Sub are in the same package.
Public members
In Scala, if no modifier is specified, it defaults to public. Such members can be accessed anywhere.
Example
class Inner {
def f() { println("f") }
class InnerMost {
f() // Correct
}
}
(new Inner).f() // Correct because f() is public
}
Package-Private access
Scala also supports the package-private access modifier, which restricts members to be accessible only within a specific package. This is done by following the private keyword with a package name. The format is:
private[x] 或 protected[x]
Here,xrefers to the package, class, or singleton object it belongs to.
If written asprivate[x], it reads as"This member is private to all other classes except the classes in […] or the classes in the package […] and their companion objects."。
This technique is very useful in large projects that span several packages. It allows you to define things that are visible in several subpackages of your project but remain invisible to clients outside the project.
Example
package navigation{
private[bobsrockets] class Navigator{
protected[navigation] def useStarChart(){}
class LegOfJourney{
private[Navigator] val distance = 100
}
private[this] var speed = 200
}
}
package launch{
import navigation._
object Vehicle{
private[launch] val guide = new Navigator
}
}
}
In the above example, class Navigator is marked as private[bobsrockets], meaning this class is visible to all classes and objects contained in the bobsrockets package.
For example, access to Navigator from the Vehicle object is allowed because the Vehicle object is contained in the launch package, and the launch package is in bobsrockets. Conversely, any code outside the bobsrockets package cannot access class Navigator.
Companion objects and companion classes
In Scala, companion objects and companion classes can access each other's private members. A companion object and its companion class are a class and an object with the same name and in the same file.
Example
private val privateField: String = "I am private in class"
}
object CompanionExample {
def accessPrivateField(example: CompanionExample): String = {
example.privateField // Companion object can access the private members of the class
}
}
object Main {
def main(args: Array[String]): Unit = {
val example = new CompanionExample
println(CompanionExample.accessPrivateField(example))
}
}