Scala中限定为所在包的私有顶级类的作用域范围是什么?
关于Scala中
private[z]修饰顶级类的作用解析 嘿,我完全懂你为啥会疑惑——平时用private[xxx]大多是给上层包开放权限,突然碰到和当前类所在包同名的限定符,确实会有点摸不着头脑😉
先拆解你贴的这段代码:
package x.y.z private[z] class ExampleClass { // class body }
首先得明确:Scala里的private[enclosing]语法,本质是把访问权限开放给指定的封闭作用域,这个作用域可以是外围的类、特质,也可以是包。当你写private[z]时,这里的z指的就是x.y.z这个当前类所在的包,这么写和普通private的核心区别,得从访问范围来看:
关键差异:包内跨源文件的访问权限
- 如果是普通
private修饰的顶级类:只有当前源文件内部能访问,哪怕是同一个x.y.z包下的其他.scala文件,都看不到这个类。 - 但如果是
private[z]修饰的顶级类:整个x.y.z包下的所有源文件都能访问它,相当于模拟了Java里的包级私有(package-private)——毕竟Scala本身没有直接的包级私有关键字,就用这种显式指定的方式实现。
举个实际例子就明白了:
- 先在
x/y/z/FileA.scala里写:
package x.y.z private[z] class ExampleClass { def sayHi() = println("Hi!") }
- 再创建同包下的
x/y/z/FileB.scala:
package x.y.z object Test { val obj = new ExampleClass() // 这里能正常编译,因为private[z]开放了包内访问 obj.sayHi() }
但如果把ExampleClass改成普通private,那FileB里的代码直接编译报错——跨源文件访问私有顶级类是Scala不允许的。
为啥要这么设计?
Scala的权限控制理念是「精细化显式授权」,不会默认开放包级权限。所以private[z]其实是明确告诉编译器:把这个类的访问权限开放给它所在的x.y.z包,和private[y]开放给上层x.y包的逻辑完全一致——只是这里的作用域刚好是当前类所在的包而已。
最后再总结一下不同写法的权限范围:
private顶级类:仅当前源文件可见private[z]顶级类:整个x.y.z包内所有源文件可见private[y]顶级类:整个x.y包(包括子包x.y.z)内所有源文件可见
这样是不是就清晰多了?本质就是Scala把权限控制做的更细,哪怕是当前包,也要显式指定才能开放跨文件的访问权限~
内容的提问来源于stack exchange,提问作者Matteo
相关产品推荐
相关产品推荐

