Когда следует использовать специальный идентификатор Scala `package`?

В Scala вы можете определить объекты пакета. Таким образом, вы можете получить доступ к этому объекту пакета, записав имя пакета, а затем `package`:

// file package.scala in src/com

package com
package object test {
  val Version = 2
}

// file Test.scala in src/test

package test
object Test {
  def main(args: Array[String]) {
    val p = com.test.`package`          // get ref on package object
    val v1 = com.test.`package`.Version // (1) get val
    val v2 = com.test.Version           // (2) get val
  }
}

В чем разница между (1) и (2)? В некоторых случаях мне приходилось писать дополнительные `package` для запуска моего кода. Должна ли быть разница или это ошибка компилятора?

Кроме того, что, например, эта линия означает, что в Predef.scala?

scala.`package`   // to force scala package object to be seen.

Ответ 1

Просто слепое предположение: линия

scala.`package`

приводит к простому getstatic (код объекта пакета), за которым следует pop. Поэтому он ничего не делает, кроме инициализации объекта пакета, если он еще не был инициализирован раньше.

Итак, я предполагаю, что в Predef.scala вы не можете быть уверены (или может быть определенно, что этого не произошло), что объект пакета уже инициализирован. Большинство других модулей могут неявно зависеть от загружаемого Predef, поэтому эти модули нельзя просто инициализировать вслепую. Поэтому необходимо обеспечить это, включив модуль/пакет/объект явно в Predef. То же самое делается для модуля List и StringBuilder. Таким образом, это может быть просто указание порядка инициализации.

Ответ 2

В вашем коде нет разницы между (1) и (2). Объект пакета позволяет вам записать его как (2). Но вы все еще можете писать как (1).

Я могу только представить себе, что случаи, в которых вам приходилось писать package в вашем коде, должны что-то сделать с вашей средой разработки (Eclipse/Scala плагин?), ожидая, что класс с именем "package" будет создан из источник с именем "package.scala", а не "test.scala". Можете ли вы воспроизвести случаи, когда вам пришлось писать package?

Мне также интересно, что эффект этой линии в Predef.

Ответ 3

Как я понимаю, объекты пакета (введенные в Scala 2.8) означают, что все объявленные внутри них автоматически попадают в рамки другого кода в том же пакете. Таким образом, объект пакета в Predef.scala содержит вещи, импортированные в область верхнего уровня Scala. Мартин Одерски, создатель Scala, написал хорошее введение в них в Artima год назад.

Ответ 4

Слово package является зарезервированным ключевым словом в Scala. Однако это имя (идентификатор) объектов пакета. Поэтому, если вам нужен прямой доступ к объекту пакета, вам нужно использовать backquotes для "escape" пакета слов.

Следующее определение эквивалентно тому, которое вы отправили в своем вопросе:

// file package.scala in src/com
package com.test
object `package` {
  val Version = 2
}

Кроме того, строка в Predef.scala

scala.`package`   // to force scala package object to be seen.

позволяет вам напрямую обращаться к объекту пакета как к любому другому объекту.