在 Scala 中,访问修饰符用于控制类、对象、方法、变量等的可访问性。通过访问修饰符,可以指定代码的哪些部分是公开的、哪些部分是私有的,从而确保数据的封装和保护。

Scala 提供了几种访问修饰符,其中包括 public(默认),privateprotected。这些修饰符可以用于类、方法、字段等。


📖 目录

  1. public 访问修饰符
  2. private 访问修饰符
  3. protected 访问修饰符
  4. private[this]private[scope]
  5. 成员与类的访问控制
  6. 自定义访问修饰符
  7. 参考资料

1. public 访问修饰符

在 Scala 中,默认的访问修饰符是 public。这意味着如果没有显式指定访问修饰符,成员(方法、字段等)默认是公开的,可以被类外部的代码访问。

示例:

class Person(val name: String, var age: Int) {
  def greet(): Unit = {
    println(s"Hello, my name is $name and I am $age years old.")
  }
}

val person = new Person("Alice", 30)
println(person.name)   // 公开成员,访问成功
person.greet()         // 公开方法,访问成功

在这个例子中,nameage 变量以及 greet() 方法没有显式的访问修饰符,因此它们是公开的,可以在类外部访问。


2. private 访问修饰符

private 修饰符用于限制成员的可访问性,表示该成员只能在当前类或对象内部访问。类外部无法直接访问私有成员。它用于数据封装,确保外部无法直接修改类的内部状态。

示例:

class Person(val name: String, private var age: Int) {
  def showAge(): Unit = {
    println(s"I am $age years old.")
  }
}

val person = new Person("Alice", 30)
println(person.name)      // 公开成员,访问成功
// println(person.age)    // 错误:无法访问 private 成员
person.showAge()          // 可以通过方法访问 private 变量

在这个例子中,age 被声明为 private,所以它只能在 Person 类的内部访问,外部代码不能直接访问 age 变量,但可以通过 showAge() 方法间接访问它。


3. protected 访问修饰符

protected 修饰符使成员可以在当前类和其子类(继承类)中访问。与 private 不同,protected 允许子类继承和访问父类的成员,但父类外部的代码无法访问这些成员。

示例:

class Animal {
  protected val name: String = "Unknown"
}

class Dog extends Animal {
  def printName(): Unit = {
    println(s"The dog's name is $name.")
  }
}

val dog = new Dog
dog.printName()   // 输出:The dog's name is Unknown
// println(dog.name)   // 错误:无法访问 protected 成员

在这个例子中,nameprotected,因此它可以被 Dog 类访问,但无法直接从 Animal 类的外部访问。


4. private[this]private[scope]

除了常见的 privateprotected,Scala 还提供了更细粒度的控制:

  • private[this]:表示该成员只能在当前对象实例中访问,无法通过其他对象实例访问同一类的成员。
  • private[scope]:表示该成员对指定的范围(如包、类等)内的代码可见。

示例:

private[this] 示例:

class Person(val name: String) {
  private[this] var age: Int = 30
  
  def birthday(): Unit = {
    age += 1
  }
}

val person1 = new Person("Alice")
val person2 = new Person("Bob")
// println(person1.age)   // 错误:无法访问 private[this] 成员

private[scope] 示例:

package mypackage {

  class Person {
    private[mypackage] val name: String = "Alice"
  }

}

val person = new mypackage.Person
// println(person.name)   // 错误:无法访问 private[mypackage] 成员

private[this] 示例中,age 只能在 Person 类的同一个实例中访问。而在 private[scope] 示例中,namemypackage 包内的代码是可见的,但包外的代码无法访问。


5. 成员与类的访问控制

Scala 的访问修饰符不仅可以应用于类成员,还可以应用于类本身。例如,类可以被声明为 privateprotected,限制对该类的访问。

示例:

private 类:

private class SecretClass {
  def secret(): String = "This is a secret."
}

// 无法在外部创建 SecretClass 的实例
// val secret = new SecretClass()  // 错误:类是 private 的

protected 类:

protected class ProtectedClass {
  def reveal(): String = "This class is protected."
}

class SubClass extends ProtectedClass {
  def display(): Unit = {
    println(reveal())
  }
}

val sub = new SubClass
sub.display()  // 输出:This class is protected


6. 自定义访问修饰符

除了 Scala 内置的 privateprotectedpublic,你还可以自定义访问修饰符,指定可访问范围的特定位置,例如在包内或类内部等。

示例:

class MyClass {
  private[myPackage] var internalData = "Some data"
}

object MyApp {
  def main(args: Array[String]): Unit = {
    val myClass = new MyClass
    // println(myClass.internalData)  // 错误:无法访问 private[myPackage] 成员
  }
}


7. 参考资料


通过合理使用访问修饰符,Scala 允许你灵活控制类和对象的成员的访问权限,确保代码封装性和安全性,并在需要时公开特定的功能。