Как вызвать метод T eq (Object) интерфейса Java из Scala? - PullRequest
12 голосов
/ 01 сентября 2011

Scala определяет класс AnyRef, который после компиляции интерпретируется как класс объектов Java. Класс AnyRef, однако, не совсем эквивалентен Object с точки зрения языка, потому что он вводит несколько новых методов, таких как eq (), который принимает AnyRef и возвращает Boolean и сравнивает ссылки на идентичность

Если в Java есть класс, который сам определяет метод eq () с другим типом результата и интерфейс, который этот класс реализует, также имеет этот метод:

public interface I {
    String eq(Object that);
}

public class A implements I {
    public String eq(Object that) {return "";}
}

тогда его метод eq становится недоступным для кода Scala, если вызывается через ссылку на интерфейс

val i: I = new A
val a = new A
val b = Some(1)           //whatever actually
val s1: String = a.eq(b)   //compiles OK
val s2: String = i.eq(b)   //compilation error

Метод eq, о котором Scala знает здесь, это метод eq из класса AnyRef, который «приклеивается» к интерфейсу I, пришедший из Java без этого метода, но с собственным методом eq () с другим типом результата. Я могу объяснить это поведение, но не могу решить реальную задачу, когда мне нужно вызвать этот метод Java eq () без возможности изменить код сторонней библиотеки Java. А именно, я говорю о Liferay и его API динамических запросов и интерфейсе с именем com.liferay.portal.kernel.dao.orm.Property. У него есть метод eq (), принимающий Object и возвращающий критерий. Этот код не будет компилироваться в Scala:

val query = DynamicQueryFactoryUtil.forClass(classOf[BookmarksEntry])
.add(PropertyFactoryUtil.forName("folderId").eq(new Long(folderId)))

потому что eq не будет правильно интерпретирован. Отметим, что у класса Property есть еще одна перегрузка метода eq (), которая принимает DynamicQuery в качестве параметра. Эта перегрузка доступна из Scala.

Вам известен способ вызова этого метода eq (Object) интерфейса Java из Scala?

Используемая версия Scala - 2.8.1

.

Ответы [ 3 ]

5 голосов
/ 01 сентября 2011

Интересная проблема: я раньше такого не видел. Я не знаю, как решить это в Scala, или даже если это вообще возможно. Однако в таких ситуациях лучшее, что вы можете сделать, - это создать оболочку на Java. Например:

public class Eq {
    static public String eq(I obj, Object that) {
        return obj.eq(that);
}

Затем вы просто звоните Eq.eq(x, y) вместо x.eq(y).

3 голосов
/ 01 сентября 2011

Вы можете сделать это с помощью рефлексии, но я не знаю, хотите ли вы этого, потому что это довольно уродливо.

FWIW, вы можете сделать это:

i.getClass().getMethod("eq", classOf[Object]).invoke(i, "a").asInstanceOf[String]
1 голос
/ 01 сентября 2011

Я не должен все понимать, потому что это кажется слишком очевидным.Если (i:I).eq(o): String не работает, но A.eq(o): String работает, почему это не работает?

scala> i.asInstanceOf[A].eq(b)
res2: java.lang.String = str

Итак

val query = DynamicQueryFactoryUtil.forClass(classOf[BookmarksEntry])
  .add(PropertyFactoryUtil.forName("folderId").asInstanceOf[XYZ]
  .eq(new Long(folderId)))

(замените XYZ на любой конкретный класс, в котором создан экземпляртакие как com.liferay.portal.dao.orm.hibernate.PropertyImpl)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...