Сопутствующий объект не может получить доступ к закрытой переменной класса

Довольно странное поведение, исходящее из Scala REPL.

Хотя следующее компилируется без проблем:

class CompanionObjectTest {
    private val x = 3
}
object CompanionObjectTest {
    def testMethod(y:CompanionObjectTest) = y.x + 3
}

приватная переменная, кажется, не доступна из сопутствующего объекта в REPL:

scala> class CompanionObjectTest {
     | 
     | private val x = 3;
     | }
defined class CompanionObjectTest

scala> object CompanionObjectTest {
     | 
     | def testMethod(y:CompanionObjectTest) = y.x + 3
     | }
<console>:9: error: value x in class CompanionObjectTest cannot be accessed in CompanionObjectTest
       def testMethod(y:CompanionObjectTest) = y.x + 3
                                                 ^

Почему это происходит?

2 ответа

Решение

Происходит то, что каждая "строка" в REPL на самом деле помещается в отдельный пакет, поэтому класс и объект не становятся компаньонами. Вы можете решить это несколькими способами:

Сделайте определения класса и объекта цепочки:

scala> class CompanionObjectTest {
     |   private val x = 3;
     | }; object CompanionObjectTest {
     |   def testMethod(y:CompanionObjectTest) = y.x + 3
     | }
defined class CompanionObjectTest
defined module CompanionObjectTest

Использовать режим вставки:

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

class CompanionObjectTest {
    private val x = 3
}
object CompanionObjectTest {
    def testMethod(y:CompanionObjectTest) = y.x + 3
}

// Exiting paste mode, now interpreting.

defined class CompanionObjectTest
defined module CompanionObjectTest

Поместите все внутри объекта:

scala> object T {
     | class CompanionObjectTest {
     |     private val x = 3
     | }
     | object CompanionObjectTest {
     |     def testMethod(y:CompanionObjectTest) = y.x + 3
     | }
     | }
defined module T

scala> import T._
import T._

Это действительно немного странно. Чтобы обойти эту проблему, вы должны сначала войти в режим вставки с :paste, затем определите ваш класс и ваш сопутствующий объект и выйдите из режима вставки с помощью CTRL-D. Вот пример сеанса REPL:

Welcome to Scala version 2.9.0.1 (OpenJDK Server VM, Java 1.6.0_22).
Type in expressions to have them evaluated.
Type :help for more information.

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

class A { private val x = 0 }
object A { def foo = (new A).x }

// Exiting paste mode, now interpreting.

defined class A
defined module A

scala> 
Другие вопросы по тегам