Как Scala обрабатывает операторы пакета в стиле Java

Это звучит неловко. Моя цель — понять, как Scala обрабатывает операторы пакетов, написанные в стиле Java. С этой целью я написал небольшой пример класса (который я назвал DinnerTimeP.scala, как показано ниже:

package dinnertime
 class Dinner { 
  val veggie = "broccoli"
   def announceDinner(veggie: String) {
   println("Dinner happens to be tasteless " + veggie + " soup")
  }
 }

У меня есть папка с именем scaladev, в которой я создал папку пакета, ужин. Под этим пакетом живет DinnerTimeP.scala. Затем по команде DOS я перехожу к обеду и компилирую файл DinnerTimeP (название звучит глупо) с помощью scalac, как показано ниже.

C:\scala-2.9.1.final\scala-2.9.1.final\scaladev\dinnertime>set CLASSPATH=.;C:\scala-  2.9.1.final\scala-2.9.1.final\scaladev

C:\scala-2.9.1.final\scala-2.9.1.final\scaladev\dinnertime>scalac DinnerTimeP.scala

Я надеялся найти Dinner.class, сгенерированный прямо в папке ужина и находящийся рядом с исходным файлом DinnerTimeP.scala. Чтобы подтвердить свое понимание, я создал программу HelloWorld.java в той же папке:

package dinnertime;

public class HelloWorld {
  public static void main(String[] args) {
  System.out.println("Hello World");
}

}

Я скомпилировал HelloWorld.java в командной строке следующим образом: C:\scala-2.9.1.final\scala-2.9.1.final\scaladev\dinnertime>javac HelloWorld.java

Файл HelloWorld.class был сгенерирован рядом с исходным файлом. Это была именно та ситуация, которую я хотел увидеть с исходным файлом Scala и его скомпилированным файлом. Вместо этого я вижу новую папку пакета, сгенерированную Scala, внутри обеденной папки пакета.

Это может быть наивно. Я, вероятно, предаю фундаментальное понимание Scala и пакетов, но такое поведение меня озадачило. Это проблема, которую я не могу объяснить себе: почему вложенный пакет создается для вновь созданного файла класса. Это проблема, которую я надеялся решить, основываясь на своих собственных искренних усилиях. Поскольку мой опыт работы со Scala в настоящее время ограничен, я обратился к гуру Scala на stackoverflow, чтобы они помогли мне понять, что происходит. и почему? Есть ли причина, по которой этот вложенный пакет создается Scala, а не Java?


person ilango    schedule 19.07.2012    source источник


Ответы (2)


Томаш объяснено все, что вам нужно, чтобы заставить его работать, поэтому позвольте мне объяснить, почему.

Scala не требует, чтобы исходные файлы находились в иерархии каталогов, отражающей пакеты. То есть Dinner.scala может быть где угодно: это просто не имеет значения.

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

Извините, что уделяю этому столько внимания, но, исходя из Java, это может быть трудно понять.

Хорошо, теперь, как объяснить dinnertime/Dinner.class? Что ж, JVM требует, чтобы файл класса был помещен в иерархию каталогов, соответствующую именам пакетов, поэтому, даже если исходные файлы Scala могут быть помещены в произвольные каталоги, scalac должен создавать выходные данные, структура каталогов которых отражает названия пакетов.

Итак, чтобы просмотреть все, Scala не волнует, в каком каталоге вы находитесь, поэтому он проигнорировал тот факт, что вы находитесь в каталоге с именем dinnertime. Однако, поскольку в исходном коде указано, что класс находится в пакете с именем dinnertime, он создал такой каталог и поместил в него файл класса. Предполагается, что базой для этого был текущий каталог, который можно изменить с помощью параметра -d, согласно ответу Томаша.

person Daniel C. Sobral    schedule 19.07.2012
comment
Я вижу все это сейчас. Это очень очень полезная информация. Я ценю потрясающие отзывы и всю тяжелую работу, которую вы приложили, чтобы объяснить вещи. - person ilango; 20.07.2012

Прежде всего попробуйте скомпилировать из корневого каталога, чтобы dinnertime был подкаталогом:

$ javac dinnertime/HelloWorld.java

и:

$ scalac dinnertime/Dinner.scala

Оба они выдают один и тот же результат, т. е. в обоих случаях файл .class помещается в подкаталог dinnertime.

Разница возникает, когда вы запускаете компилятор внутри пакета. Оказывается, javac достаточно умен, чтобы поместить целевые двоичные файлы относительно корневого каталога, а не текущего каталога. Это не относится к scalac, который всегда использует текущий каталог в качестве базы. Вы можете легко исправить это, используя параметр -d:

$ cd dinnertime
$ scalac -d .. Dinner.scala
person Tomasz Nurkiewicz    schedule 19.07.2012
comment
Я только что запустил scalac -d Вот что я сделал: C:\scala-2.9.1.final\scala-2.9.1.final\scaladev\dinnertime›scalac -d DinnerTimeP.scala ошибка scalac: DinnerTimeP.scala не существует или это не каталог Что-то не так с тем, что я делаю. - person ilango; 20.07.2012
comment
@ilangogurusamy: -d ожидает какого-то аргумента: scalac -d some/dir DinnerTimeP.scala - person Tomasz Nurkiewicz; 20.07.2012
comment
Обновление: это сработало. Мне было любопытно узнать о .., и я сначала игнорировал его и запускал scalac -d, но когда я попробовал это с .., это сработало. Это замечательно. - person ilango; 20.07.2012
comment
И Дэниелс, и ваши ответы вполне приемлемы для меня. Как таковые оба верны. Но я не могу установить правильный ответ на оба. - person ilango; 23.07.2012
comment
@ilangogurusamy: нет проблем, рад, что смог помочь! - person Tomasz Nurkiewicz; 24.07.2012