Как вы вызываете одноэлементный метод Scala из Java? - PullRequest
22 голосов
/ 19 июля 2010

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

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

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

Ответы [ 5 ]

17 голосов
/ 10 августа 2010

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

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

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

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

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

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

РЕДАКТИРОВАТЬ: Опечатка

10 голосов
/ 19 июля 2010

Какие ошибки вы получили? Используя ваш пример Scala и следующий класс Java:

cat test.java * * 1004


import org.fun.*;

public class test {
    public static void main(String args[]) {
       System.out.println("show my power: " + ScalaPower.showMyPower(3));       
    }
}

И работает так:

java -cp .:<<em>path-to/scala/install-dir</em>>/lib/scala-library.jar test

дает мой вывод:

show my power: 0, 1, 2

9 голосов
/ 20 июля 2010

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

Сопутствующие объекты и статика Java Методы

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

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

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

3 голосов
/ 19 июля 2010

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

1 голос
/ 10 августа 2010

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

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

ScalaPower.showMyPower(10) работает как положено.

...