Я пытаюсь ввести некоторый код Scala в свое существующее приложение Java. (Так, быть сказанным, я хочу еще некоторую забаву).
Я создаю одноэлементный материал в Scala
ScalaPower.scala
package org.fun
class ScalaPower
object ScalaPower{
def showMyPower(time:Int) = {
(0 to time-1).mkString(", ")
}
}
Теперь, в OldJava.java
class OldJava {
public void demo(){
System.out.println(?)
}
}
Что я должен заполнить ?
так, чтобы Java назвал showMyPower метод? Я попробовал обоих org.fun.ScalaPower.showMyPower(10)
и org.fun.ScalaPower.getInstance().showMyPower(10)
но ни один не работает.
(Декомпилируйтесь, файл класса с помощью Вруба показывают мне только код ерунды.)
Редактирование я удаляю class ScalaPower
объявление и scala производят статический метод как ожидалось. (звоните в org.fun.ScalaPower.showMyPower(10)
просто работы).
Удивление, если это - ошибка в scala компиляторе или нет
Я думаю, что это косвенно охватывает это:
Companion Objects and Java Static Методы
Есть еще одна вещь, которую нужно знать о объектах-компаньонах. Всякий раз, когда вы определяете главный метод для использования в качестве точки входа в приложение, Scala требует, чтобы вы поместили его в объект. Однако на момент написания этой статьи главные методы не могут быть определены в объекте-компаньоне. Из-за деталей реализации в сгенерированном коде, JVM не сможет найти главный метод. Эта проблема может быть решена в одном из будущих выпусков. На данный момент, вы должны определить любой главный метод в синглтонном объекте (т.е. "некомпаньонном" объекте) [ScalaTips]. Рассмотрим следующий пример простого класса Person и объекта-компаньона объект, который пытается определить main.
Как здесь: http://programming-scala.labs.oreilly.com/ch06.html
Короче говоря, поскольку ваш объект является объектом-компаньоном (имеет класс-компаньон), вы не можете вызвать его, как вы ожидаете. Как вы обнаружили, если вы избавитесь от класса, он будет работать.
Какие ошибки вы получали? Используя ваш образец Scala и следующий класс Java:
cat test.java
:
import org.fun.*;
public class test {
public static void main(String args[]) {
System.out.println("show my power: " + ScalaPower.showMyPower(3));
}
}
И запустите его следующим образом:
java -cp.: < path-to / scala / install- dir > / lib / scala-library.jar test
дает мой результат:
показать мою мощность: 0, 1, 2
Имейте в виду, что можно использовать стандартный инструмент javap
чтобы увидеть, что производит компилятор Scala. Конечно, он не дает прямого ответа на ваш вопрос, но когда вам нужно просто напомнить о шаблонах генерации кода, этого достаточно.
Обычно лучше получить доступ к синглтону напрямую из его собственного класса.
В данном случае:
org.fun.ScalaPower$.MODULE$.showMyPower(10);
Не вдаваясь в подробности реализации, Scala различает пространства имен между Object и Class / Trait. Это означает, что они могут использовать одно и то же имя. Однако у объекта есть класс, и поэтому ему нужно искаженное имя на JVM. Текущие соглашения Scala заключаются в добавлении символа $ в конце имени модуля (для модулей верхнего уровня). Если объект определен в классе, я считаю, что соглашение - OuterClass $ ModuleName $. Для принудительного применения одноэлементного свойства модуля ScalaPower существует также статический член MODULE $ класса ModuleName $. Это инициализируется во время загрузки класса, гарантируя, что существует только один экземпляр. Побочным эффектом этого является то, что вы не должны выполнять какие-либо блокировки в конструкторе модуля.
В любом случае, Scala также имеет встроенный механизм статических перенаправителей «сделать вещи лучше для Java». Здесь он пишет статические методы класса ScalaPower, которые просто вызывают ScalaPower $ .MODULE $ .someMethod (). Если вы также определяете сопутствующий класс, число серверов пересылки, которые могут быть сгенерированы, ограничено, поскольку вам не разрешается иметь конфликты имен со статическими методами и методами уровня экземпляра на JVM. Я думаю, что в 2.8.0 это означает, что если у вас есть объект-компаньон, вы теряете свои статические пересылки.
В этом случае «наилучшей практикой» было бы всегда использовать ссылку ScalaPower $ .MODULE $ вместо статического сервера пересылки, поскольку этот сервер пересылки может исчезнуть с изменениями в классе ScalaPower.
РЕДАКТИРОВАТЬ: Опечатка
После выполнения
class ScalaPower
object ScalaPower{
def showMyPower(time:Int) = {
(0 to time-1).mkString(", ")
}
}
ScalaPower.showMyPower (10)
работает должным образом.