为什么在编译时,伴侣对象可以在其伴侣类中访问私有val,而在解释时却不能这样做?

Jul*_*ang 1 scala read-eval-print-loop companion-object

// Script A.scala
class A {
    private val privateVal = 1
}
object A extends App{ 
    println(new A().privateVal)
}
Run Code Online (Sandbox Code Playgroud)

A.scala可以编译和运行,因为伴侣对象及其类可以访问彼此的私有成员,因此不会出现问题。

$ scalac A.scala
$ scala A
1
Run Code Online (Sandbox Code Playgroud)

为什么在解释时相同的代码会显示伴随对象无法访问其伴随类中的私有val?

$ scala A.scala
error: value privateVal in class A cannot be accessed in A
Run Code Online (Sandbox Code Playgroud)

yǝs*_*ǝla 6

为了在Scala中获得伴侣对象,必须在同一文件中定义一个类及其伴侣对象。看起来这就是您正在执行的操作,尤其是当您不使用解释器时。

但是,当您在Scala中逐行解释代码时,它将代码包装在其他匿名对象中,以允许在没有显式类或REPL中的对象的情况下定义表达式(更多信息请参见此处)。

这是包装问题的说明:

不起作用:

$ scala
Welcome to Scala version 2.10.6 (OpenJDK 64-Bit Server VM, Java 1.8.0_222).
Type in expressions to have them evaluated.
Type :help for more information.

scala> class A {
     |     private val privateVal = 1
     | }
defined class A

scala> object A extends App{ 
     |     println(new A().privateVal)
     | }
<console>:9: error: value privateVal in class A cannot be accessed in A
           println(new A().privateVal)
                           ^
Run Code Online (Sandbox Code Playgroud)

如果同时使用:paste以下命令定义,则可以使用:

scala> :paste
// Entering paste mode (ctrl-D to finish)

// Script A.scala
class A {
    private val privateVal = 1
}
object A extends App{ 
    println(new A().privateVal)
}

// Exiting paste mode, now interpreting.

defined class A
defined module A
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我在运行时没有遇到这个问题scala A.scala。也许我使用的是其他版本或设置。

如果您不能使用粘贴模式,或者无法使解释器立即读取整个文件,则解决方法是将代码包装在任何对象中,以强制解释单个代码块:

scala> object Workaround {
     | class A {
     |     private val privateVal = 1
     | }
     | object A extends App{ 
     |     println(new A().privateVal)
     | }
     | }
defined module Workaround
Run Code Online (Sandbox Code Playgroud)