Scala:通过包装外的结构类型访问包可见方法

这不能像预期的那样工作(因为我试图从外部服务器调用一个私人运行包):

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

这是一个语言功能还是规则,我在Scala中缺少或合法地出现错误

解决方法

在JVM层级可见性作用域到周围的实例/类型不存在.在这种情况下,Scala编译器将生成一个公共方法,并在内部处理此可见性.

如果使用结构类型,编译器将反射访问此类型的成员.它不会检查Scala特定的可见性标志,但只检查在Java字节码中定义的可见性标志.

您没有提到您正在使用的Scala编译器版本,但我认为这是您特定版本中的错误.尝试编译时,我得到与Jasper-M相同的结果.原因是编译器生成方法实际上以类型名称为前缀,即在这种情况下运行HelloPrinter $$.以下代码将执行:

val x: { def HelloPrinter$$run: String  } = new HelloPrinter
x.run

Scala编译器再次生成一个公共方法,并在内部管理可见性.这不是一个功能,而是编译器不检查结构类型的Scala内部可见性的错误.

相关文章

共收录Twitter的14款开源软件,第1页Twitter的Emoji表情 Tw...
Java和Scala中关于==的区别Java:==比较两个变量本身的值,即...
本篇内容主要讲解“Scala怎么使用”,感兴趣的朋友不妨来看看...
这篇文章主要介绍“Scala是一种什么语言”,在日常操作中,相...
这篇文章主要介绍“Scala Trait怎么使用”,在日常操作中,相...
这篇文章主要介绍“Scala类型检查与模式匹配怎么使用”,在日...