Подтвердить что ты не робот

Scala: доступ к видимым методам пакета через структурные типы вне пакета

Это не работает должным образом (поскольку я пытаюсь вызвать закрытый run пакет Services):

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?

4b9b3361

Ответ 1

На уровне JVM видимость, охваченная окружающими экземплярами/типами, не существует. Компилятор Scala генерирует публичный метод в этом случае и обрабатывает эту видимость внутренне.

Если вы используете структурные типы, компилятор будет обращать внимание на членов этого типа. Он не будет проверять флаги видимости Scala, но только те, которые определены в байт-коде Java.

Вы не указали, какую версию компилятора Scala вы используете, но я предполагаю, что это ошибка в вашей конкретной версии. Я получаю тот же результат, что и Jasper-M, пытаясь его скомпилировать. Причина в том, что метод, который генерируется компилятором, на самом деле имеет префикс имени типа, т.е. HelloPrinter$$run в этом случае. Выполняется следующий код:

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

Опять компилятор Scala просто генерирует открытый метод и управляет видимостью внутри. Это не функция, а скорее ошибка, которую компилятор не проверяет Scala - внутреннюю видимость для структурных типов.