Когда следует использовать специальный идентификатор 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.
позволяет вам напрямую обращаться к объекту пакета как к любому другому объекту.