Объект Companion не может получить доступ к закрытой переменной класса

Скорее странное поведение, исходящее из 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
                                                 ^

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

Ответ 1

Что происходит, так это то, что каждая "строка" на 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._

Ответ 2

Это действительно немного странно. Чтобы обойти эту проблему, вы должны сначала ввести режим вставки с помощью :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>