Как вы вызываете метод 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) работает, как ожидалось.