Подтвердить что ты не робот

Как вы называете метод Scala singleton из Java?

Я пытаюсь ввести некоторый код 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), но никто не работает.

(Декомпилируйте файл класса с помощью Jad, покажите мне ничего, кроме бессмысленного кода.)

Edit Я удаляю объявление class ScalaPower и Scala создает статический метод, как ожидалось. (вызов только org.fun.ScalaPower.showMyPower(10) работает).

Интересно, если это ошибка в компиляторе Scala или нет

4b9b3361

Ответ 1

Я думаю, это косвенно покрывает это:

Объекты Companion и Java Static Методы

Есть еще одна вещь, о которой нужно знать сопутствующие объекты. Всякий раз, когда вы определяете основной метод использования в качестве записи точка приложения, Scalaтребует, чтобы вы поместили его в объект. Однако, на момент написания этой статьи, основные методы не могут быть определены в сопутствующий объект. Из-за детали реализации в сгенерированный код, JVM не найдет основной метод. Эта проблема может быть разрешено в будущем выпуске. На данный момент, вы должны определить какой-либо основной метод в одиночный объект (т.е. объект "non-companion" ) [ScalaTips]. Рассмотрим следующий пример простой класс и компаньон объект, который пытается определить основной.

Как найти здесь: http://programming-scala.labs.oreilly.com/ch06.html

Короче, потому что ваш Объект является сопутствующим объектом (имеет сопутствующий класс), вы не можете называть его, как вы ожидаете. Как вы обнаружили, если вы избавитесь от класса, он будет работать.

Ответ 2

Обычно лучше получить доступ к singleton непосредственно из собственного класса.

В этом случае:

org.fun.ScalaPower$.MODULE$.showMyPower(10);

Не вдаваясь в подробности реализации, Scala выделяет пространства имен между Object и Class/Trait. Это означает, что они могут использовать одно и то же имя. Тем не менее, объект имеет класс и поэтому нуждается в искаженном имени в JVM. Текущие соглашения Scala должны добавить $в конце имени модуля (для модулей верхнего уровня). Если объект определен в классе, я считаю, что это соглашение OuterClass $ModuleName $. Чтобы обеспечить соответствие свойства singleton модуля ScalaPower, существует также статический член MODULE $класса ModuleName $. Это инициализируется во время загрузки класса, гарантируя наличие только одного экземпляра. Побочным эффектом этого является то, что вы не должны делать каких-либо блокировок в конструкторе модуля.

В любом случае, Scala также встроил в него механизм создания "статических-форвардеров" для Java. Здесь он записывает статические методы в классе ScalaPower, которые просто вызывают ScalaPower $.MODULE $.someMethod(). Если вы также определяете класс компаньона, форвардеры, которые могут быть сгенерированы, ограничены, так как вам не разрешено конфликты имен со статическими и экземплярами на JVM-уровне. Я думаю, что в 2.8.0 это означает, что если у вас есть объект-компаньон, вы теряете свои статические экспедиторы.

В этом случае "наилучшей практикой" было бы всегда использовать ссылку ScalaPower $.MODULE $вместо статического пересылки, поскольку форвардер может исчезнуть с модификациями класса ScalaPower.

EDIT: Typo

Ответ 3

Какие ошибки вы получали? Используя образец 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

Ответ 4

Имейте в виду, что средство запаса javap может использоваться для просмотра того, что производит компилятор Scala. Разумеется, он не отвечает на ваш вопрос напрямую, но когда вам нужно просто напомнить о шаблонах генерации кода, достаточно.

Ответ 5

После выполнения

class ScalaPower 
object ScalaPower{
  def showMyPower(time:Int) = {
    (0 to time-1).mkString(", ")
  }
}

ScalaPower.showMyPower(10) работает как ожидалось.