这不能像预期的那样工作(因为我试图从外部服务器调用一个私人运行包):
object Services { class HelloPrinter { private[Services] def run = "Hello" } } val obj = new Services.HelloPrinter
但令人惊讶的是,
val obj: {def run: String} = new Services.HelloPrinter obj.run
我会说,它是编译器中的一个错误,因为由于包名可见性规则,HelloPrinter与结构类型不匹配,所以不应该编译!
这是程序编译但是会抛出运行时异常(java.lang.NoSuchMethodException)的情况:
class HelloPrinter { private[HelloPrinter] def run = "Hello" } val obj: {def run: String} = new HelloPrinter obj.run
解决方法
在JVM层级可见性作用域到周围的实例/类型不存在.在这种情况下,Scala编译器将生成一个公共方法,并在内部处理此可见性.
如果使用结构类型,编译器将反射访问此类型的成员.它不会检查Scala特定的可见性标志,但只检查在Java字节码中定义的可见性标志.
您没有提到您正在使用的Scala编译器版本,但我认为这是您特定版本中的错误.尝试编译时,我得到与Jasper-M相同的结果.原因是编译器生成的方法实际上以类型名称为前缀,即在这种情况下运行HelloPrinter $$.以下代码将执行:
val x: { def HelloPrinter$$run: String } = new HelloPrinter x.run
Scala编译器再次生成一个公共方法,并在内部管理可见性.这不是一个功能,而是编译器不检查结构类型的Scala内部可见性的错误.