Skip to content

Scala Access Modifiers

Access modifiers control the visibility of classes and their members in Scala. This chapter details public, private, protected, and package-private modifiers.

Basic Access Modifiers

Public Access

scala
object PublicAccess {
  class PublicClass {
    // Public fields (default)
    val publicField = "public field"
    
    // Public methods (default)
    def publicMethod(): String = "Public method"
    
    // Explicit public declaration
    public def explicitPublicMethod(): String = "Explicitly public"
  }
  
  object PublicExample {
    def main(args: Array[String]): Unit = {
      val obj = new PublicClass()
      println(s"Public field: ${obj.publicField}")
      println(obj.publicMethod())
      println(obj.explicitPublicMethod())
    }
  }
}

Private Access

scala
object PrivateAccess {
  class PrivateClass {
    // Private fields
    private val privateField = "private field"
    
    // Private methods
    private def privateMethod(): String = "Private method"
    
    // Public method calling private
    def accessPrivate(): String = {
      privateField
      s"Accessing private field: $privateField"
    }
  }
}
  
  object PrivateExample {
    def main(args: Array[String]): Unit = {
      val obj = new PrivateClass()
      // println(obj.accessPrivate())
    }
  }
}

Protected Access

scala
object ProtectedAccess {
  class Parent {
    protected val protectedField = "protected field"
    protected def protectedMethod(): String = "Protected method"
  }
  
  class Child extends Parent {
    // Can access protected members
    def accessProtected(): String = {
      protectedMethod()
      s"Accessing protected field: $protectedField"
    }
  }
}
  
  object ProtectedExample {
    def main(args: Array[String]): Unit = {
      val child = new Child()
      println(child.accessProtected())
    }
}
}

Package Private Access

scala
package com.example.scalanpackage
  
object PackageExample {
  def publicMethod(): String = "Public method"
  
  private privateMethod(): String = "Private method"
  
  private[scala] packagePrivateMethod(): String = "Package private"
}

Class Access Modifiers

Final Classes

scala
object FinalClasses {
  final class ImmutableClass(val value: String) {
    def getValue: String = value
  }
  
  object FinalExample {
    def main(args: Array[String]): Unit = {
      val immutable = new ImmutableClass("test")
      println(immutable.getValue())  // Cannot override
    }
  }
}

Sealed Classes

scala
object SealedClassExample {
  sealed trait Status
  case object Active extends Status
  case object Inactive extends Status
  
  def processStatus(status: Status): String = status match {
    case Active => "System is active"
    case Inactive => "System is inactive"
    case _ => "Unknown status"
  }
  
  def main(args: Array[String]): Unit = {
    println(processStatus(Active))
    println(processStatus(Inactive))
  }
}

Companion Objects and Private Members

scala
object CompanionExample {
  class Counter {
    private var count = 0
      
    def increment(): Unit = count += 1
    
    def getCount: Int = count
  }
  
  object Counter {
    def create(initialValue: Int): Counter = new Counter {
      private var count = initialValue
      
    def increment(): Unit = count += 1
    
    def getCount: Int = count
  }
  }
  
  def main(args: Array[String]): Unit = {
    val counter = Counter.create(10)
    println(s"Initial count: ${counter.getCount}")
    counter.increment()
    println(s"After increment: ${counter.getCount}")
    
    val counter2 = new Counter(5)
    println(s"Second counter: ${counter2.getCount}")
    counter2.increment()
    println(s"After increment: ${counter2.getCount}")
  }
  }
}

Best Practices

  1. Use default visibility:

    • Make fields public by default
    • Hide implementation details with private
  2. Use protected wisely:

    • For methods that need to be overridden
    • For internal state that needs access in subclasses
  3. Minimize visibility:

    • Restrict access to what's necessary
    • Use private for internal implementation
  4. Use final when appropriate:

    • For classes that shouldn't be extended
    • For constants
  5. Consider package private:

    • For implementation details that don't need exposure outside package
    • For package-internal utilities

Access modifiers are essential for encapsulation and information hiding in object-oriented programming.

Content is for learning and research only.