Scala 访问权限详解:private、protected 与 private

导入

在 Scala 面向对象编程中,访问权限控制是封装性的重要体现。通过合理的访问权限设置,可以保护类的内部状态,提高代码的安全性和可维护性。本文将详细讲解 Scala 中的三种主要访问权限:private、protected 和 privatethis,并通过具体代码示例展示它们的使用场景和区别。

一、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) 会编译报错,体现了"在类的外部不能访问"
  • 在伴生对象 Studenttest 方法中,可以访问 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 的 weightsayWeight 方法
  • Major 子类中,sayAge() 调用会报错,因为 private 成员在子类中不可访问
  • sayWeight() 调用正常执行,因为 protected 成员在子类中可以访问
  • main 方法中直接访问 s1.weight 会报错,体现了 protected 成员在类外部不可访问

三、privatethis 访问权限

定义

privatethis 是 Scala 中最严格的访问权限,限制了成员只能在当前对象实例中访问。

语法特点

  • 在类的内部可以访问
  • 在类的外部不能访问
  • 在伴生对象中不能访问
  • 在子类中不能访问

示例:privatethis 的严格限制

代码

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] 修饰,只能在当前对象实例中访问
  • 在伴生对象 Studenttest 方法中,可以访问普通的 private var age
  • 但访问 student.pwd 会编译报错,体现了 private[this] 在伴生对象中也不可访问

四、案例

示例:使用 privatethis 保护账户余额

代码

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] 修饰,确保余额只能在当前对象实例中访问
  • 通过公共方法 depositwithdrawgetBalance 来安全地操作和查询余额
  • 在伴生对象 Bankclear 方法中,直接设置 bank.balance = 0 会编译报错
  • 这种设计确保了账户余额的安全性,防止外部直接修改

总结

Scala 提供了多层次的访问权限控制,从宽松到严格依次为:

  1. protected - 允许类内部、伴生对象和子类访问
  2. private - 允许类内部和伴生对象访问
  3. privatethis - 只允许当前对象实例访问
相关推荐
hopsky9 天前
《Scala 学习手册》核心内容详解
人工智能·学习·scala
abcy07121319 天前
scala playframework 搭建与新建controller教程
scala
lpfasd12320 天前
编程语言榜单变迁分析
开发语言·后端·scala
戮漠summer1 个月前
Missing Semester 计算机教育中缺失的一课 Lecture 01 Shell
开发语言·后端·scala
醉熏的石头2 个月前
Ubuntu 中的编程语言(中)
linux·ubuntu·scala
Irene19912 个月前
Scala、Java、Python、JavaScript 的核心特性和应用场景(Python 的“单机“局限性:GIL 机制导致的多核并行缺陷)
java·javascript·python·scala
李白的天不白2 个月前
确认 Nginx 配置文件是否真的生效
scala
醉颜凉3 个月前
Scala自定义Monad实战:从理论到应用的完整指南
大数据·算法·scala
那晚的她3 个月前
Scala中Set集合
开发语言·后端·scala
IvanCodes3 个月前
二、Scala流程控制:分支与循环
大数据·scala