Scala – Access Modifiers and Access qualifiers in Detail

If You are interested to learn about the Scala Data types

Access Modifiers in scala are used to define the access field of members of packages, classes or objects in scala. Members of packages, classes or objects can be labeled with the access modifiers private and protected, and if we are not using either of these two keywords, then access will be assumed as public. These modifiers restrict accesses to the members to certain regions of code. To use an access modifier, you include its keyword in the definition of members of package, class or object as we will see in the following section.

Private Members

A private member is visible only inside the class or object that contains the member definition.

Following is the example code snippet to explain Private member −

Example

class Outer {
   class Inner {
      private def f() { println("f") }
      
      class InnerMost {
         f() // OK
      }
   }
   (new Inner).f() // Error: f is not accessible
}

In Scala, the access (new Inner). f() is illegal because f is declared private in Inner and the access is not from within class Inner. By contrast, the first access to f in class Innermost is OK, because that access is contained in the body of class Inner. Java would permit both accesses because it lets an outer class access private members of its inner classes.

Protected Members

A protected member is only accessible from subclasses of the class in which the member is defined. Following is the example code snippet to explain protected member −

Example

package p {
   class Super {
      protected def f() { println("f") }
   }
   
   class Sub extends Super {
      f()
   }
   
   class Other {
      (new Super).f() // Error: f is not accessible
   }
}

The access to f in class Sub is OK because f is declared protected in ‘Super’ class and ‘Sub’ class is a subclass of Super. By contrast the access to f in ‘Other’ class is not permitted, because class ‘Other’ does not inherit from class ‘Super’. In Java, the latter access would be still permitted because ‘Other’ class is in the same package as ‘Sub’ class.

Public Members

Unlike private and protected members, it is not required to specify Public keyword for Public members. There is no explicit modifier for public members. Such members can be accessed from anywhere. Following is the example code snippet to explain public member −

Example

class Outer {
   class Inner {
      def f() { println("f") }
      
      class InnerMost {
         f() // OK
      }
   }
   (new Inner).f() // OK because now f() is public
}

Scope of Protection

Access modifiers in Scala can be augmented with qualifiers. A modifier of the form private[X] or protected[X] means that access is private or protected “up to” X, where X designates some enclosing package, class or singleton object.

Consider the following example −

Example

package society {
   package professional {
      class Executive {
         private[professional] var workDetails = null
         private[society] var friends = null
         private[this] var secrets = null

         def help(another : Executive) {
            println(another.workDetails)
            println(another.secrets) //ERROR
         }
      }
   }
}

Note − the following points from the above example −

  • Variable workDetails will be accessible to any class within the enclosing package professional.
  • Variable friends will be accessible to any class within the enclosing package society.
  • Variable secrets will be accessible only on the implicit object within instance methods (this).

Access qualifiers

Scala’s protected and private access modifiers have an interesting feature that give you more fine-grained control. You can add a qualifier after the keywords protected and private, between square brackets. The qualifier can be one of two things: the name of an enclosing scope (package, class, trait or object), or the keyword this. These two kinds of qualifiers have different meanings.

Qualified access to an enclosing scope

With a qualifier that refers to an enclosing scope, you can widen the accessibility of a private or protected member to that scope, so that it’s not only accessible in the immediate enclosing scope, but in a scope that is one or more levels higher up. For example:

package outside {
  package inside {
    object Messages {
      // Accessible up to package 'inside'
      private[inside] val Insiders = "Hello Friends"
      // Accessible up to package 'outside'
      private[outside] val Outsiders = "Hello People"
    }
    object InsideGreeter {
      def sayHello(): Unit =
        // Can access both messages
        println(Messages.Insiders + " and " + Messages.Outsiders)
    }
  }
  object OutsideGreeter {
    def sayHello(): Unit =
      // Can only access the 'Outsiders' message
      println(inside.Messages.Outsiders)
  }
}

Note that the name between the square brackets must be a simple name; it cannot be a fully-qualified name (with parts separated by dots).

Qualified access to ‘this’

Normally, in both Java and Scala, when a member of a class or trait is private or protected, this means that the access is restricted to the class or trait. Access is not restricted to individual instances; an instance of a class can access the same member in other instances of the same class.

In Scala it is possible to restrict access to the same instance only by qualifying the access modifier with [this], making the member object-private or object-protected. This means that an instance of a class or trait can only access the member in the current instance, and not in other instances. For example:

class Counter {
  // Normal private member variable
  private var total = 0
  // Object-private member variable
  private[this] var lastAdded = 0
  def add(n: Int): Unit = {
    total += n
    lastAdded = n
  }
  def copyFrom(other: Counter): Unit = {
    // OK, private member from other instance is accessible
    total = other.total
    // ERROR, object-private member from other instance is not accessible
    lastAdded = other.lastAdded
  }
}

Access modifiers – differences and similarities with Java

Differences

  • Public — Unlike Java, Scala has no explicit modifier for public members.
  • Protected members in Java have wider access than in Scala; Java’s protected members can be accessible not only from within the class or within its subclasses, but also from other classes in the same package.
  • Default access modifier — Java defaults to package internal visibility, while Scala, on the other hand, defaults to public, i.e. can be accessed from anywhere.
  • Java adopts an all-or-nothing access strategy, i.e., either it’s visible to all classes in the current package or it’s not visible to any, whereas Scala gives fine-grained control over visibility.
  • Object-private scope — Scala private[this] takes privacy a step further than private scope and makes the fields and methods object-private which means they can only be accessed from the object that contains them.

Similarities

  • Private members in Scala are treated similarly to Java.

Conclusion

The access modifiers in Scala are slightly different than in Java. In my opinion, they are better in Scala, for the following reasons:

  • Public is the default in Scala, which is more useful than Java’s default access level, which is rarely useful in practice in Java code.
  • protected has the same meaning in Scala as in C++; only accessible in the class itself and in subclasses. Fortunately Scala didn’t inherit Java’s weird idea, where protected members are also accessible in unrelated classes that happen to be in the same package.
  • The meaning of private top-level types in Scala makes sense.
  • When you accidentally expose a type that has restricted access from a less restricted method, Scala gives you an error at the declaration of the method (the actual source of the error) rather than at the point where you try to call the method.
  • With qualifiers, and because Scala understands nested packages, you have more fine-grained control over accessibility in Scala than in Java.
  • In Scala you can make members really really private by restricting access to only the current instance, which isn’t possible in Java.
Scala – Access Modifiers and Access qualifiers in Detail
Show Buttons
Hide Buttons