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



这没有像预期的那样工作(因为我试图从Services外部调用私有run包):

object Services {
 class HelloPrinter {
   private[Services] def run = "Hello"
  }  
}
val obj = new Services.HelloPrinter

但是,令人惊讶的是,这是有效的:

val obj: {def run: String} = new Services.HelloPrinter
obj.run

我想说,这是编译器中的一个bug,因为HelloPrinter不匹配结构类型,因为包可见性规则,它根本不应该编译!

下面是程序编译但是抛出运行时异常(java.lang.NoSuchMethodException)的情况:

class HelloPrinter {
  private[HelloPrinter] def run = "Hello"
}  
val obj: {def run: String} = new HelloPrinter
obj.run

这是我遗漏的语言功能或规则还是Scala中的合法bug ?

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

如果使用结构类型,编译器将反射地访问该类型的成员。它不会检查特定于scala的可见性标志,而只检查Java字节码中定义的可见性标志。

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

val x: { def HelloPrinter$$run: String  } = new HelloPrinter
x.run
同样,Scala编译器只是生成一个公共方法并在内部管理可见性。编译器没有检查scala内部结构类型的可见性,这不是一个特性,而是一个bug。

相关内容

  • 没有找到相关文章

最新更新