Как вы вызываете метод Scala singleton из Java?
Я пытаюсь ввести некоторый код Scala в мое существующее Java-приложение. (Итак, как говорится, Я хочу еще повеселиться).
Я создаю одноэлементный материал в Scala
ScalaPower.scala
package org.fun
class ScalaPower
object ScalaPower{
def showMyPower(time:Int) = {
(0 to time-1).mkString(", ")
}
}
теперь внутри Олдьявы.java
class OldJava {
public void demo(){
System.out.println(?)
}
}
что я должен заполнить в ?
Так что Java вызовет метод showMyPower?
Я попробовал оба org.fun.ScalaPower.showMyPower(10)
и org.fun.ScalaPower.getInstance().showMyPower(10)
но никто не работает.
(декомпилировать файл класса с помощью Jad показать мне ничего, кроме ерунды код.)
редактировать
Я удаляю class ScalaPower
объявление и scala производят статический метод, как ожидалось. (позовите org.fun.ScalaPower.showMyPower(10)
просто работает).
интересно, если это ошибка в компиляторе scala или нет
5 ответов
Я думаю, что это косвенно охватывает его:
сопутствующие объекты и статические Java Методы
есть еще одна вещь, о которой нужно знать сопутствующие объекты. Всякий раз, когда вы определяете основной метод для использования в качестве записи точка приложения, Scala требует, чтобы вы поместили его в объект. Однако, на момент написания этой статьи, основные методы не могут быть определены в сопутствующий объект. Потому что детали внедрения в сгенерированный код, JVM не будет найти основной метод. Эта проблема может быть решено в будущем выпуске. Пока, необходимо определить основной метод в одноэлементный объект (т. е. a объект" non-companion") [ScalaTips]. Рассмотрим следующий пример класс и компаньон simple Person объект, который пытается определить главное.
Как найдено здесь:http://programming-scala.labs.oreilly.com/ch06.html
короче говоря, потому что ваш объект является объектом-компаньоном (имеет компаньона класс) вы не можете назвать это так, как ожидаете. Как вы обнаружили, если вы избавитесь от класса, он будет работать.
обычно лучше получить доступ к синглтону непосредственно из его собственного класса.
в этом случае:
org.fun.ScalaPower$.MODULE$.showMyPower(10);
Не вдаваясь в детали реализации, Scala различает пространства имен между объектом и классом/признаком. Это означает, что они могут использовать то же имя. Однако объект имеет класс и поэтому нуждается в искаженном имени в JVM. Текущие соглашения Scala должны добавить $ в конце имени модуля (для модулей верхнего уровня). Если объект определен в классе, я считаю, что соглашение является OuterClass$ModuleName$. Чтобы применить свойство singleton модуля ScalaPower, существует также статический модуль$ член класса ModuleName$. Это инициализируется во время загрузки класса, гарантируя, что существует только один экземпляр. Побочным эффектом этого является то, что вы должны не сделайте любую блокировку в конструкторе модуля.
в любом случае, Scala также встроила в него "сделать вещи приятнее для Java" статическ-механизм товароотправителей. Здесь он пишет статические методы в классе ScalaPower, который просто вызывает ScalaPower$.МОДУЛЬ.$someMethod (). Если вы также определяете сопутствующий класс, пересылки, которые могут быть созданы, ограничены, так как вам не разрешено иметь конфликты имен со статическими методами и методами уровня экземпляра в JVM. Я думаю, что в 2.8.0 это означает, что если у вас есть объект, вы потеряете свой статический экспедиторов.
в этом случае "лучшей практикой" будет всегда используйте ScalaPower$.Модуль$ reference вместо статического форвардера, так как форвардер может исчезнуть с изменениями класса ScalaPower.
EDIT: Typo
какие ошибки вы получаете? Используя образец 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
мой вывод:
show my power: 0, 1, 2
имейте в виду, что акции javap
инструмент можно использовать, чтобы увидеть, что производит компилятор Scala. Конечно, это не прямой ответ на ваш вопрос, но когда вам нужно просто напомнить о шаблонах генерации кода, этого достаточно.
после этого
class ScalaPower
object ScalaPower{
def showMyPower(time:Int) = {
(0 to time-1).mkString(", ")
}
}
ScalaPower.showMyPower(10)
работает, как ожидалось.