Scala中的访问权限

26 阅读6分钟

(一)Scala的访问权限概述

Scala中的属性、方法可以通过访问控制符来设置不同的访问权限。不同的访问控制符可以决定是否可以被外部类访问。

Scala 的访问权限控制比 Java 更加精细和灵活,提供了多种访问修饰符。

1. 基本访问权限

默认访问权限(public)

class DefaultAccess {
  val publicField: String = "默认是public"  // 任何地方都可访问
  def publicMethod(): Unit = println("公共方法")
}

private 成员

class PrivateExample {
  private val privateField: String = "私有字段"
  
  private def privateMethod(): Unit = {
    println("私有方法")
  }
  
  def accessPrivate(): Unit = {
    println(privateField)  // ✅ 同类中可以访问
    privateMethod()        // ✅ 同类中可以访问
  }
}

object Test {
  def test(): Unit = {
    val example = new PrivateExample()
    // println(example.privateField)  // ❌ 编译错误
    // example.privateMethod()        // ❌ 编译错误
  }
}

protected 成员

class ProtectedExample {
  protected val protectedField: String = "受保护字段"
  
  protected def protectedMethod(): Unit = {
    println("受保护方法")
  }
}

class SubClass extends ProtectedExample {
  def accessProtected(): Unit = {
    println(protectedField)  // ✅ 子类中可以访问
    protectedMethod()        // ✅ 子类中可以访问
  }
}

object Test {
  def test(): Unit = {
    val example = new ProtectedExample()
    // println(example.protectedField)  // ❌ 编译错误
    // example.protectedMethod()        // ❌ 编译错误
  }
}

2. Scala 特有的作用域保护

private[this] - 对象私有

class ThisPrivateExample {
  private[this] val objectPrivate: String = "对象私有"
  
  private val normalPrivate: String = "普通私有"
  
  def compare(other: ThisPrivateExample): Unit = {
    println(normalPrivate)        // ✅ 可以访问
    println(other.normalPrivate)  // ✅ 可以访问其他对象的普通私有
    
    println(objectPrivate)        // ✅ 可以访问
    // println(other.objectPrivate)  // ❌ 不能访问其他对象的objectPrivate
  }
}

protected[this] - 对象保护的

class ThisProtectedExample {
  protected[this] val objectProtected: String = "对象保护的"
  
  def accessSelf(): Unit = {
    println(objectProtected)  // ✅ 可以访问自己的
  }
}

class SubClass2 extends ThisProtectedExample {
  def compare(other: SubClass2): Unit = {
    println(objectProtected)        // ✅ 可以访问自己的
    // println(other.objectProtected)  // ❌ 不能访问其他对象的
  }
}

3. 包级访问权限

private[package] - 包内访问

package com.example {
  package services {
    
    class Service {
      // 在 com.example 包及其子包中都可以访问
      private[example] val packagePrivate: String = "包内可访问"
      
      // 只在 services 包内可访问
      private[services] val servicesPrivate: String = "services包内可访问"
    }
    
    class AnotherService {
      def test(): Unit = {
        val service = new Service()
        println(service.packagePrivate)    // ✅ 同包内可访问
        println(service.servicesPrivate)   // ✅ 同包内可访问
      }
    }
  }
  
  package utils {
    class Util {
      def test(): Unit = {
        val service = new services.Service()
        println(service.packagePrivate)    // ✅ 同example包下可访问
        // println(service.servicesPrivate) // ❌ 不同包不能访问
      }
    }
  }
  
  package external {
    class External {
      def test(): Unit = {
        val service = new services.Service()
        // println(service.packagePrivate)  // ❌ 不在example包下不能访问
      }
    }
  }
}

4. 伴生对象特殊访问规则

class CompanionExample {
  private val privateField: String = "私有字段"
  private[this] val objectPrivate: String = "对象私有"
  
  def access(): Unit = {
    println(CompanionExample.companionPrivate)  // ✅ 类可以访问伴生对象的私有
  }
}

object CompanionExample {
  private val companionPrivate: String = "伴生对象私有"
  
  def testAccess(instance: CompanionExample): Unit = {
    println(instance.privateField)      // ✅ 伴生对象可以访问类的私有
    // println(instance.objectPrivate)  // ❌ 不能访问对象的objectPrivate
    println(companionPrivate)           // ✅ 可以访问自己的私有
  }
}

5. 访问权限总结表

修饰符同类同包子类其他包其他对象
默认
private
protected
private[this]
protected[this]✅*
private[pkg]✅**✅**
protected[pkg]✅**✅**

*注:子类只能访问自己的,不能访问父类实例的
*注:在指定包及其子包内可访问

6. 构造器访问权限

// 主构造器为private
class PrivateConstructor private (name: String) {
  def show(): Unit = println(name)
}

object PrivateConstructor {
  // 只能在伴生对象中创建实例
  def create(name: String): PrivateConstructor = new PrivateConstructor(name)
}

// 使用
// val obj = new PrivateConstructor("test")  // ❌ 编译错误
val obj = PrivateConstructor.create("test")   // ✅ 正确

7. 实际应用示例

package business {
  package domain {
    
    class User private[domain] (val id: Long, val name: String) {
      // 包内可访问的字段
      private[domain] var email: String = _
      
      // 对象私有,用于内部状态
      private[this] var loginCount: Int = 0
      
      // 公共方法
      def login(): Unit = {
        loginCount += 1
        println(s"$name 登录成功")
      }
      
      // 包内可访问的方法
      private[domain] def getLoginCount: Int = loginCount
    }
    
    object UserService {
      def createUser(id: Long, name: String): User = {
        val user = new User(id, name)
        user.email = s"$name@example.com"
        user
      }
      
      def showStats(user: User): Unit = {
        println(s"登录次数: ${user.getLoginCount}")  // ✅ 同包可访问
      }
    }
  }
  
  package web {
    class UserController {
      def displayUser(): Unit = {
        // val user = new User(1, "张三")  // ❌ 不能访问包内构造器
        val user = domain.UserService.createUser(1, "张三")
        user.login()  // ✅ 可以访问公共方法
        // println(user.email)  // ❌ 不能访问包内字段
        // domain.UserService.showStats(user)  // ❌ 不能访问包内方法
      }
    }
  }
}

Scala 的访问权限控制提供了更细粒度的控制能力,特别是在包级访问和对象级访问方面,使得代码的封装性更加灵活和强大。

(二)Scala的属性访问权限

有四种访问控制权限,分别为:

(1)默认访问权限。Scala中的默认访问权限相当于Java中的public,Scala中如果一个变量没有任何修饰符,就代表默认访问权限。作用域:全部

(2)protected访问权限。作用域:本类,子类

(3)private访问权限。作用域:类内部(伴生对象:定义方法传入类的对象)

(4)private[this]访问权限。

Scala 提供了多种精细的属性访问权限控制机制。

1. 基本访问修饰符

默认访问(public)

class PublicExample {
  var publicVar: String = "公共属性"        // 可读可写
  val publicVal: String = "公共只读属性"    // 只读
}

object TestPublic {
  def test(): Unit = {
    val example = new PublicExample()
    println(example.publicVar)     // ✅ 可读
    example.publicVar = "新值"     // ✅ 可写
    println(example.publicVal)     // ✅ 可读
    // example.publicVal = "错误"   // ❌ 编译错误:val不可重新赋值
  }
}

private 属性

class PrivateExample {
  private var privateVar: String = "私有属性"
  private val privateVal: String = "私有只读属性"
  
  def showPrivate(): Unit = {
    println(privateVar)    // ✅ 同类中可访问
    println(privateVal)    // ✅ 同类中可访问
    privateVar = "修改值"  // ✅ 同类中可修改
  }
  
  // 提供公共访问器
  def getPrivateVal: String = privateVal
  def setPrivateVar(value: String): Unit = {
    privateVar = value
  }
}

object TestPrivate {
  def test(): Unit = {
    val example = new PrivateExample()
    // println(example.privateVar)  // ❌ 编译错误
    // println(example.privateVal)  // ❌ 编译错误
    example.showPrivate()           // ✅
    println(example.getPrivateVal)  // ✅ 通过方法访问
    example.setPrivateVar("新值")   // ✅ 通过方法修改
  }
}

protected 属性

class ProtectedExample {
  protected var protectedVar: String = "受保护属性"
  protected val protectedVal: String = "受保护只读属性"
}

class SubClass extends ProtectedExample {
  def accessProtected(): Unit = {
    println(protectedVar)     // ✅ 子类中可访问
    println(protectedVal)     // ✅ 子类中可访问
    protectedVar = "子类修改"  // ✅ 子类中可修改
  }
}

object TestProtected {
  def test(): Unit = {
    val example = new ProtectedExample()
    // println(example.protectedVar)  // ❌ 编译错误
    // println(example.protectedVal)  // ❌ 编译错误
    
    val sub = new SubClass()
    sub.accessProtected()  // ✅
  }
}

2. Scala 特有的作用域保护

private[this] - 对象私有

class ThisPrivateExample {
  private[this] var objectPrivateVar: String = "对象私有"
  private var normalPrivateVar: String = "普通私有"
  
  def compare(other: ThisPrivateExample): Unit = {
    println(objectPrivateVar)        // ✅ 访问自己的
    println(normalPrivateVar)        // ✅ 访问自己的
    println(other.normalPrivateVar)  // ✅ 访问其他对象的普通私有
    // println(other.objectPrivateVar) // ❌ 不能访问其他对象的objectPrivate
  }
  
  objectPrivateVar = "修改自己的"  // ✅ 可以修改自己的
}

protected[this] - 对象保护的

class ThisProtectedExample {
  protected[this] var objectProtectedVar: String = "对象保护的"
  
  def accessSelf(): Unit = {
    println(objectProtectedVar)  // ✅ 访问自己的
    objectProtectedVar = "修改"  // ✅ 修改自己的
  }
}

class SubClass2 extends ThisProtectedExample {
  def compare(other: SubClass2): Unit = {
    println(objectProtectedVar)        // ✅ 访问自己的
    // println(other.objectProtectedVar) // ❌ 不能访问其他对象的
  }
}

3. 包级访问权限

private[package] - 包内访问

package com.example {
  package services {
    
    class Service {
      // 在 com.example 包及其子包中可访问
      private[example] var packagePrivateVar: String = "包内可访问"
      
      // 只在 services 包内可访问  
      private[services] var servicesPrivateVar: String = "services包内可访问"
      
      def show(): Unit = {
        println(packagePrivateVar)
        println(servicesPrivateVar)
      }
    }
  }
  
  package utils {
    class Util {
      def test(): Unit = {
        val service = new services.Service()
        println(service.packagePrivateVar)    // ✅ 同example包下可访问
        // println(service.servicesPrivateVar) // ❌ 不同包不能访问
      }
    }
  }
}

4. 构造器参数访问权限

class ConstructorAccess(
  val publicParam: String,        // 公共只读
  var publicMutable: String,      // 公共可写
  private val privateParam: String, // 私有只读
  private var privateMutable: String // 私有可写
) {
  def show(): Unit = {
    println(publicParam)      // ✅
    println(publicMutable)    // ✅
    println(privateParam)     // ✅
    println(privateMutable)   // ✅
  }
}

object TestConstructor {
  def test(): Unit = {
    val obj = new ConstructorAccess("只读", "可写", "私有只读", "私有可写")
    
    println(obj.publicParam)    // ✅
    println(obj.publicMutable)  // ✅
    obj.publicMutable = "新值"  // ✅
    
    // println(obj.privateParam)  // ❌
    // println(obj.privateMutable) // ❌
  }
}

5. 伴生对象特殊访问

class CompanionAccess {
  private var privateVar: String = "私有变量"
  private[this] var objectPrivateVar: String = "对象私有"
  
  def testCompanion(): Unit = {
    // 类可以访问伴生对象的私有成员
    println(CompanionAccess.companionPrivate)
  }
}

object CompanionAccess {
  private var companionPrivate: String = "伴生对象私有"
  
  def accessClassPrivate(obj: CompanionAccess): Unit = {
    println(obj.privateVar)        // ✅ 伴生对象可以访问类的私有
    // println(obj.objectPrivateVar) // ❌ 不能访问对象的private[this]
    companionPrivate = "修改"       // ✅ 可以修改自己的私有
  }
}

6. 属性访问最佳实践

使用 getter/setter 模式

class Person {
  // 私有属性,提供公共访问器
  private var _name: String = _
  private var _age: Int = _
  
  // Getter 方法
  def name: String = _name
  def age: Int = _age
  
  // Setter 方法(可添加验证逻辑)
  def name_=(newName: String): Unit = {
    require(newName != null && newName.nonEmpty, "姓名不能为空")
    _name = newName
  }
  
  def age_=(newAge: Int): Unit = {
    require(newAge >= 0 && newAge <= 150, "年龄必须在0-150之间")
    _age = newAge
  }
}

object PersonTest {
  def test(): Unit = {
    val person = new Person()
    person.name = "张三"  // 调用 name_= 方法
    person.age = 25      // 调用 age_= 方法
    
    println(person.name) // 调用 name 方法
    println(person.age)  // 调用 age 方法
    
    // person.age = -5   // ❌ 运行时异常:年龄验证失败
  }
}

case class 的自动访问器

case class User(
  name: String,           // val,只读
  var age: Int,           // var,可读写
  private val id: Long    // 私有,只在类内和伴生对象中可访问
)

object UserTest {
  def test(): Unit = {
    val user = User("李四", 30, 123L)
    
    println(user.name)    // ✅ case class 自动生成getter
    // user.name = "王五" // ❌ 编译错误:name是val
    
    println(user.age)     // ✅
    user.age = 31         // ✅ age是var
    
    // println(user.id)   // ❌ 编译错误:id是private
  }
}

7. 访问权限总结表

修饰符同类同对象子类同包伴生对象其他
默认
private
protected
private[this]
protected[this]✅*
private[pkg]✅**✅**

*注:子类只能访问自己的实例
**注:在指定包及其子包内可访问

Scala 的属性访问权限控制提供了比 Java 更精细的粒度,特别是在对象级别和包级别的控制上,使得封装更加灵活和强大。

(三)private[this]的例子

更加严格的私有权限,表示该字段或方法只能在调用它的同一个实例内部可见。这意味着即使在同一类的其他实例中,也无法访问该字段或方法。不能在伴生对象中访问,不能在函数参数中访问。

[例] 银行账户存钱取钱的例子。

账户类:

  • balance 余额

  • deposit() 存钱

  • withdraw() 取钱

  • transfer(to: 账户, amount:Dobule) 转账。是调用to对象的方法来增加余额,而不是直接操作balance属性!

private[this] 是 Scala 中最严格的访问权限,表示 仅当前对象实例可访问

1. 基础示例

class StrictPrivateExample {
  private var normalPrivate: String = "普通私有"
  private[this] var objectPrivate: String = "对象私有"
  
  def show(): Unit = {
    println(s"normalPrivate: $normalPrivate")  // ✅ 可以访问
    println(s"objectPrivate: $objectPrivate")  // ✅ 可以访问自己的
  }
  
  def modify(): Unit = {
    normalPrivate = "修改普通私有"    // ✅ 可以修改
    objectPrivate = "修改对象私有"    // ✅ 可以修改自己的
  }
  
  // 测试访问其他实例的私有成员
  def compare(other: StrictPrivateExample): Unit = {
    println(s"其他实例的normalPrivate: ${other.normalPrivate}")  // ✅ 可以访问
    // println(s"其他实例的objectPrivate: ${other.objectPrivate}") // ❌ 编译错误
  }
}

object TestStrictPrivate {
  def main(args: Array[String]): Unit = {
    val obj1 = new StrictPrivateExample()
    val obj2 = new StrictPrivateExample()
    
    obj1.show()
    obj1.modify()
    obj1.show()
    
    obj1.compare(obj2)  // 测试跨对象访问
  }
}

2. 与普通 private 的对比

class ComparisonExample {
  private var counter: Int = 0           // 普通私有
  private[this] var secret: String = "秘密" // 对象私有
  
  def increment(): Unit = {
    counter += 1
    secret += "!"  // ✅ 可以修改自己的
  }
  
  def getCounter: Int = counter
  def getSecret: String = secret
  
  // 操作其他实例
  def syncWith(other: ComparisonExample): Unit = {
    // 可以访问其他实例的普通私有
    this.counter = other.counter
    
    // 不能访问其他实例的对象私有
    // this.secret = other.secret  // ❌ 编译错误
  }
  
  // 在伴生对象中的测试
  object ComparisonExample {
    def compareInstances(a: ComparisonExample, b: ComparisonExample): Unit = {
      println(s"实例a的counter: ${a.counter}")  // ✅ 伴生对象可以访问普通私有
      println(s"实例b的counter: ${b.counter}")  // ✅
      
      // println(s"实例a的secret: ${a.secret}")  // ❌ 不能访问对象私有
      // println(s"实例b的secret: ${b.secret}")  // ❌
    }
  }
}

3. 在集合操作中的应用

class Student(private[this] var _score: Int) {
  // 对象私有的成绩,连其他Student实例都不能访问
  
  def score: Int = _score  // 公共getter
  
  def updateScore(newScore: Int): Unit = {
    if (newScore >= 0 && newScore <= 100) {
      _score = newScore
    }
  }
  
  // 只能比较,不能直接访问其他学生的_score
  def isHigherThan(other: Student): Boolean = {
    this._score > other.score  // 使用公共getter访问其他实例
  }
  
  def showInfo(): Unit = {
    println(s"我的成绩: $_score")  // ✅ 可以访问自己的
  }
}

object StudentTest {
  def main(args: Array[String]): Unit = {
    val alice = new Student(85)
    val bob = new Student(92)
    
    alice.showInfo()  // 输出: 我的成绩: 85
    bob.showInfo()    // 输出: 我的成绩: 92
    
    println(s"Bob成绩比Alice高吗? ${bob.isHigherThan(alice)}")  // true
    
    // 以下操作都是不允许的:
    // println(alice._score)        // ❌ 编译错误
    // alice._score = 95           // ❌ 编译错误  
    // println(bob._score)         // ❌ 编译错误
  }
}

4. 线程安全的应用

class BankAccount {
  private[this] var _balance: Double = 0.0  // 对象私有,确保线程安全
  
  def balance: Double = _balance  // 公共getter
  
  def deposit(amount: Double): Boolean = {
    if (amount > 0) {
      _balance += amount  // ✅ 只能修改自己的余额
      true
    } else {
      false
    }
  }
  
  def withdraw(amount: Double): Boolean = {
    if (amount > 0 && _balance >= amount) {
      _balance -= amount  // ✅ 只能修改自己的余额
      true
    } else {
      false
    }
  }
  
  // 转账操作 - 不能直接操作其他账户的_balance
  def transferTo(other: BankAccount, amount: Double): Boolean = {
    if (this.withdraw(amount)) {
      other.deposit(amount)  // 通过公共方法操作其他账户
      true
    } else {
      false
    }
  }
}

object BankTest {
  def main(args: Array[String]): Unit = {
    val account1 = new BankAccount()
    val account2 = new BankAccount()
    
    account1.deposit(1000)
    account2.deposit(500)
    
    println(s"账户1余额: ${account1.balance}")  // 1000.0
    println(s"账户2余额: ${account2.balance}")  // 500.0
    
    account1.transferTo(account2, 300)
    
    println(s"转账后账户1余额: ${account1.balance}")  // 700.0
    println(s"转账后账户2余额: ${account2.balance}")  // 800.0
    
    // 以下操作都是不允许的:
    // account1._balance = 9999  // ❌ 编译错误
    // account2._balance = 8888  // ❌ 编译错误
  }
}

5. 在继承中的行为

class Parent {
  private var parentPrivate: String = "父类普通私有"
  private[this] var parentObjectPrivate: String = "父类对象私有"
  
  def showParent(): Unit = {
    println(parentPrivate)         // ✅
    println(parentObjectPrivate)   // ✅
  }
}

class Child extends Parent {
  private var childPrivate: String = "子类普通私有"  
  private[this] var childObjectPrivate: String = "子类对象私有"
  
  def showChild(): Unit = {
    println(childPrivate)         // ✅
    println(childObjectPrivate)   // ✅
    
    // 不能访问父类的对象私有
    // println(parentObjectPrivate)  // ❌ 编译错误
    
    // 也不能访问父类的普通私有(虽然继承但不可访问)
    // println(parentPrivate)        // ❌ 编译错误
  }
  
  def compareWithParent(parent: Parent): Unit = {
    // 不能访问父类实例的对象私有
    // println(parent.parentObjectPrivate)  // ❌ 编译错误
  }
}

object InheritanceTest {
  def main(args: Array[String]): Unit = {
    val child = new Child()
    child.showParent()  // 父类方法可以访问父类的对象私有
    child.showChild()   // 子类方法可以访问子类的对象私有
  }
}

6. 实际应用场景总结

适合使用 private[this] 的情况:

  1. 线程安全数据:确保每个实例的数据只能被自己修改
  2. 敏感信息:如密码、密钥等
  3. 内部状态:不希望被其他实例甚至子类访问的状态
  4. 性能优化:编译器可以更好的优化访问

示例:配置管理器

class ConfigManager {
  private[this] var _apiKey: String = _
  private[this] var _timeout: Int = _
  
  def loadConfig(key: String, timeout: Int): Unit = {
    _apiKey = key
    _timeout = timeout
  }
  
  def getApiKey: String = _apiKey
  def getTimeout: Int = _timeout
  
  // 验证配置
  def isValid: Boolean = _apiKey != null && _apiKey.nonEmpty && _timeout > 0
  
  // 不能直接操作其他配置管理器的内部状态
  def copySettingsFrom(other: ConfigManager): Unit = {
    this.loadConfig(other.getApiKey, other.getTimeout)  // 通过公共方法
  }
}

关键特点

  • 最强的封装性
  • 编译时检查,安全性最高
  • 不能通过伴生对象访问
  • 不能被子类或其他实例访问

(四)Scala的控制方法作用域

Scala的控制方法作用域有5种:

(1)默认访问权限

(2)protected访问权限

(3)private访问权限

(4)private[this]访问权限

(5)private[package] 访问权限

Scala 的方法作用域控制与属性类似,提供了多种精细的访问权限修饰符。

1. 基本访问修饰符

默认访问(public)

class PublicMethodExample {
  // 默认是public,任何地方都可访问
  def publicMethod(): String = "公共方法"
  
  def callPublic(): Unit = {
    println(publicMethod())  // ✅ 同类中可调用
  }
}

object TestPublicMethods {
  def test(): Unit = {
    val example = new PublicMethodExample()
    example.publicMethod()  // ✅ 任何地方可调用
  }
}

private 方法

class PrivateMethodExample {
  private def privateHelper(): String = "私有辅助方法"
  
  private def calculateInternal(x: Int, y: Int): Int = {
    x + y * 2
  }
  
  // 公共方法可以调用私有方法
  def publicMethod(x: Int, y: Int): Int = {
    val result = calculateInternal(x, y)  // ✅ 同类中可调用
    println(privateHelper())              // ✅ 同类中可调用
    result
  }
  
  def showPrivate(): Unit = {
    println(privateHelper())  // ✅
  }
}

object TestPrivateMethods {
  def test(): Unit = {
    val example = new PrivateMethodExample()
    example.publicMethod(5, 3)  // ✅
    // example.privateHelper()   // ❌ 编译错误
    // example.calculateInternal(1, 2) // ❌ 编译错误
  }
}

protected 方法

class ProtectedMethodExample {
  protected def protectedMethod(): String = "受保护方法"
  
  protected def validateInput(input: String): Boolean = {
    input != null && input.nonEmpty
  }
  
  def useProtected(): Unit = {
    println(protectedMethod())  // ✅ 同类中可调用
  }
}

class SubClass extends ProtectedMethodExample {
  def accessProtected(): Unit = {
    println(protectedMethod())           // ✅ 子类中可调用
    println(validateInput("test"))       // ✅ 子类中可调用
  }
  
  def processData(data: String): String = {
    if (validateInput(data)) {           // ✅ 使用父类的受保护方法
      s"处理: $data"
    } else {
      "无效输入"
    }
  }
}

object TestProtectedMethods {
  def test(): Unit = {
    val example = new ProtectedMethodExample()
    // example.protectedMethod()     // ❌ 编译错误
    // example.validateInput("test") // ❌ 编译错误
    
    val sub = new SubClass()
    sub.accessProtected()  // ✅
    sub.processData("数据") // ✅
  }
}

2. Scala 特有的作用域保护

private[this] - 对象私有方法

class ThisPrivateMethodExample {
  private def normalPrivate(): String = "普通私有方法"
  private[this] def objectPrivate(): String = "对象私有方法"
  
  def callMethods(): Unit = {
    println(normalPrivate())    // ✅ 可以调用自己的
    println(objectPrivate())    // ✅ 可以调用自己的
  }
  
  def compareWith(other: ThisPrivateMethodExample): Unit = {
    println(other.normalPrivate())    // ✅ 可以调用其他实例的普通私有
    // println(other.objectPrivate()) // ❌ 不能调用其他实例的对象私有方法
  }
}

object ThisPrivateMethodTest {
  def main(args: Array[String]): Unit = {
    val obj1 = new ThisPrivateMethodExample()
    val obj2 = new ThisPrivateMethodExample()
    
    obj1.callMethods()     // ✅
    obj1.compareWith(obj2) // ✅ (但objectPrivate调用会编译错误)
  }
}

protected[this] - 对象保护方法

class ThisProtectedMethodExample {
  protected[this] def objectProtected(): String = "对象保护方法"
  
  def callSelf(): Unit = {
    println(objectProtected())  // ✅ 可以调用自己的
  }
}

class SubClass2 extends ThisProtectedMethodExample {
  def accessMethods(): Unit = {
    println(objectProtected())  // ✅ 可以调用自己的(继承的)
  }
  
  def compare(other: SubClass2): Unit = {
    // println(other.objectProtected()) // ❌ 不能调用其他实例的对象保护方法
  }
}

3. 包级访问权限

private[package] - 包内访问方法

package com.example {
  package services {
    
    class Service {
      // 在 com.example 包及其子包中可调用
      private[example] def packagePrivateMethod(): String = "包内可访问方法"
      
      // 只在 services 包内可调用
      private[services] def servicesPrivateMethod(): String = "services包内方法"
      
      def publicMethod(): Unit = {
        println(packagePrivateMethod())    // ✅
        println(servicesPrivateMethod())   // ✅
      }
    }
    
    class AnotherService {
      def test(): Unit = {
        val service = new Service()
        service.packagePrivateMethod()    // ✅ 同包内可调用
        service.servicesPrivateMethod()   // ✅ 同包内可调用
      }
    }
  }
  
  package utils {
    class Util {
      def test(): Unit = {
        val service = new services.Service()
        service.packagePrivateMethod()    // ✅ 同example包下可调用
        // service.servicesPrivateMethod() // ❌ 不同包不能调用
      }
    }
  }
}

4. 伴生对象特殊访问

class CompanionMethodExample {
  private def classPrivateMethod(): String = "类私有方法"
  private[this] def objectPrivateMethod(): String = "对象私有方法"
  
  def testCompanion(): Unit = {
    // 类可以调用伴生对象的私有方法
    CompanionMethodExample.companionPrivateMethod()
  }
}

object CompanionMethodExample {
  private def companionPrivateMethod(): String = "伴生对象私有方法"
  
  def accessClassMethods(obj: CompanionMethodExample): Unit = {
    println(obj.classPrivateMethod())     // ✅ 伴生对象可以调用类的私有方法
    // println(obj.objectPrivateMethod()) // ❌ 不能调用对象私有方法
    companionPrivateMethod()              // ✅ 可以调用自己的私有方法
  }
}

5. 方法重写与访问权限

class MethodOverrideExample {
  protected def baseMethod(): String = "基类方法"
  
  def publicBaseMethod(): String = baseMethod()
}

class OverrideSubClass extends MethodOverrideExample {
  // 重写方法可以保持或扩大访问权限,但不能缩小
  override protected def baseMethod(): String = "子类重写方法"
  
  // 可以扩大访问权限
  override def publicBaseMethod(): String = "扩大访问权限"
  
  // 不能缩小访问权限
  // override private def baseMethod(): String = "错误" // ❌ 编译错误
}

class AnotherSubClass extends MethodOverrideExample {
  // 甚至可以改为public
  override def baseMethod(): String = "改为公共方法"
}

6. 实际应用示例

工具类设计

class StringProcessor {
  // 私有工具方法 - 内部实现细节
  private def normalizeInput(input: String): String = {
    if (input == null) ""
    else input.trim().toLowerCase()
  }
  
  private def validateLength(text: String, maxLength: Int): Boolean = {
    text.length <= maxLength
  }
  
  // 对象私有方法 - 性能计数器
  private[this] def incrementCounter(): Unit = {
    // 内部计数逻辑,不希望被其他实例访问
  }
  
  // 包内共享的工具方法
  private[example] def internalUtility(): String = {
    "包内共享工具"
  }
  
  // 公共接口
  def process(text: String, maxLen: Int): Option[String] = {
    incrementCounter()  // ✅ 调用对象私有方法
    
    val normalized = normalizeInput(text)  // ✅ 调用私有方法
    
    if (validateLength(normalized, maxLen)) {  // ✅ 调用私有方法
      Some(normalized)
    } else {
      None
    }
  }
}

模板方法模式

abstract class DataProcessor {
  // 受保护的方法,子类可以重写
  protected def validate(data: String): Boolean
  
  protected def transform(data: String): String
  
  protected def postProcess(result: String): String = {
    // 默认实现,子类可以选择性重写
    result.toUpperCase()
  }
  
  // 私有工具方法,子类不能访问或重写
  private def logProcessing(data: String): Unit = {
    println(s"处理数据: $data")
  }
  
  // 对象私有方法,用于内部状态管理
  private[this] def updateStats(): Unit = {
    // 更新处理统计
  }
  
  // 公共模板方法
  final def process(data: String): Option[String] = {
    logProcessing(data)  // ✅
    
    if (validate(data)) {
      val transformed = transform(data)
      val result = postProcess(transformed)
      updateStats()  // ✅
      Some(result)
    } else {
      None
    }
  }
}

class ConcreteProcessor extends DataProcessor {
  override protected def validate(data: String): Boolean = {
    data != null && data.length > 3
  }
  
  override protected def transform(data: String): String = {
    s"转换后的: $data"
  }
  
  // 可以重写受保护的方法
  override protected def postProcess(result: String): String = {
    s"*** ${super.postProcess(result)} ***"
  }
  
  // 不能访问或重写私有方法
  // override private def logProcessing(data: String): Unit = {} // ❌
}

7. 访问权限总结表

修饰符同类同对象子类同包伴生对象其他
默认
private
protected
private[this]
protected[this]✅*
private[pkg]✅**✅**

*注:子类只能调用自己的实例
**注:在指定包及其子包内可调用

8. 最佳实践

  1. 使用私有方法隐藏实现细节
  2. 使用对象私有方法保护内部状态
  3. 使用包级私有方法在模块内共享工具
  4. 使用受保护方法为子类提供扩展点
  5. 保持公共接口简洁,隐藏复杂实现

这样的方法作用域控制使得代码更加模块化、安全且易于维护。