(一)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] 的情况:
- 线程安全数据:确保每个实例的数据只能被自己修改
- 敏感信息:如密码、密钥等
- 内部状态:不希望被其他实例甚至子类访问的状态
- 性能优化:编译器可以更好的优化访问
示例:配置管理器
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. 最佳实践
- 使用私有方法隐藏实现细节
- 使用对象私有方法保护内部状态
- 使用包级私有方法在模块内共享工具
- 使用受保护方法为子类提供扩展点
- 保持公共接口简洁,隐藏复杂实现
这样的方法作用域控制使得代码更加模块化、安全且易于维护。