导入
在 Scala 面向对象编程中,访问权限控制是封装性的重要体现。通过合理的访问权限设置,可以保护类的内部状态,提高代码的安全性和可维护性。本文将详细讲解 Scala 中的三种主要访问权限:private、protected 和 private[this],并通过具体代码示例展示它们的使用场景和区别。
一、private 访问权限
定义
private 是 Scala 中最严格的访问权限修饰符,用于限制成员只能在特定范围内访问。
语法特点
- 在类的内部可以访问
- 在类的外部不能访问
- 在伴生对象中可以访问
示例:private 基本使用
代码
scala
package level02
object base3101 {
class Student(var name: String, private var age: Int) {
def say(): Unit = {
println(s"${this.age}") //(1)在类的内部可以访问。
}
}
object Student {
def test(student: Student): Unit = {
println(student.age) //(3)在伴生对象中可以访问。
}
}
def main(args: Array[String]): Unit = {
val s1 = new Student("小花", 18)
s1.say()
// println(s1.age) // 报错。(2)在类的外部不能访问。
Student.test(s1)
}
}
结果展示
18
18
代码分析
- 在
Student类的say方法中,可以直接访问private var age,体现了"在类的内部可以访问" - 在
main方法中,注释掉的println(s1.age)会编译报错,体现了"在类的外部不能访问" - 在伴生对象
Student的test方法中,可以访问student.age,体现了"在伴生对象中可以访问"
二、protected 访问权限
定义
protected 访问权限比 private 稍宽松,除了具备 private 的访问特性外,还允许在子类中访问。
语法特点
- 在类的内部可以访问
- 在类的外部不能访问
- 在伴生对象中可以访问
- 在子类中可以访问(与 private 的主要区别)
示例:protected 与继承
代码
scala
package level02
object base3102 {
class Student(var name: String, private var age: Int, protected var weight: Int) {
def say(): Unit = {
println(s"${this.age}, ${this.weight}") //(1)在类的内部可以访问。
}
private def sayAge():Unit = {println(age)}
protected def sayWeight():Unit = { println(weight) }
}
object Student {
def test(student: Student): Unit = {
println(student.weight) //(3)在伴生对象中可以访问。
}
}
class Major(name: String, age: Int, weight: Int) extends Student(name, age, weight) {
// 在子类中通过 super来访问父类
// sayAge() // 报错(4)private修饰的,在子类中无法访问。
sayWeight() // 正常(4)protected修饰的,在子类中可以访问。
}
def main(args: Array[String]): Unit = {
val s1 = new Student("小花", 18, 100)
s1.say()
// println(s1.weight) // 报错。(2)在类的外部不能访问。
Student.test(s1)
}
}
结果展示
18, 100
100
代码分析
Student类中有 private 的age、protected 的weight和sayWeight方法- 在
Major子类中,sayAge()调用会报错,因为 private 成员在子类中不可访问 sayWeight()调用正常执行,因为 protected 成员在子类中可以访问- 在
main方法中直接访问s1.weight会报错,体现了 protected 成员在类外部不可访问
三、private[this] 访问权限
定义
private[this] 是 Scala 中最严格的访问权限,限制了成员只能在当前对象实例中访问。
语法特点
- 在类的内部可以访问
- 在类的外部不能访问
- 在伴生对象中不能访问
- 在子类中不能访问
示例:private[this] 的严格限制
代码
scala
package level02
object base3103 {
class Student(var name: String, private var age: Int, protected var weight: Int) {
private[this] var pwd = 123 // 密码
}
object Student {
def test(student: Student): Unit = {
println(student.age) // 普通的private在伴生对象中可以访问
// println(student.pwd) 报错 (3)在伴生对象中,不能访问private[this]
}
}
def main(args: Array[String]): Unit = {
val s1 = new Student("小花", 18, 100)
Student.test(s1)
}
}
结果展示
18
代码分析
pwd字段使用private[this]修饰,只能在当前对象实例中访问- 在伴生对象
Student的test方法中,可以访问普通的private var age - 但访问
student.pwd会编译报错,体现了private[this]在伴生对象中也不可访问
四、案例
示例:使用 private[this] 保护账户余额
代码
scala
package level02
object class18 {
class Bank(private[this] var balance: Double) {
// 存钱
def deposit(amount: Double): Unit = {
balance += amount
}
// 取
def withdraw(amount: Double): Unit = {
if (balance >= amount) {
balance -= amount
}
}
def getBalance(): Double = balance
}
object Bank {
def clear(bank: Bank): Unit = {
// bank.balance = 0 // 在第11行,添加了private[this] 之后,就不能再直接访问balance属性
}
}
def main(args: Array[String]): Unit = {
val bank = new Bank(100)
bank.deposit(1000)
bank.withdraw(200)
Bank.clear(bank)
println(bank.getBalance())
}
}
结果展示
900
代码分析*
Bank类的balance使用private[this]修饰,确保余额只能在当前对象实例中访问- 通过公共方法
deposit、withdraw和getBalance来安全地操作和查询余额 - 在伴生对象
Bank的clear方法中,直接设置bank.balance = 0会编译报错 - 这种设计确保了账户余额的安全性,防止外部直接修改
总结
Scala 提供了多层次的访问权限控制,从宽松到严格依次为:
- protected - 允许类内部、伴生对象和子类访问
- private - 允许类内部和伴生对象访问
- private[this] - 只允许当前对象实例访问