Scala定义了一个AnyRef类,它在编译之后被解释为Java的Object类。然而,从语言的角度来看,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
Scala知道的eq方法是将AnyRef类中的eq方法“粘合”到没有该方法的来自Java的接口I,但是使用了自己的eq()方法,具有不同的结果类型。 我可以解释这种行为,但是当我不得不调用这个Java eq()方法而无法修改Java第三方库的代码时,无法解决现实生活中的任务。 即我正在谈论Liferay及其Dynamic Query API和名为com.liferay.portal.kernel.dao.orm.Property的接口。它有一个采用Object并返回Criterion的eq()方法。此代码不会在Scala中编译:
val query = DynamicQueryFactoryUtil.forClass(classOf[BookmarksEntry])
.add(PropertyFactoryUtil.forName("folderId").eq(new Long(folderId)))
因为eq无法正确解释。 简而言之,Property类有另一个eq()方法的重载,它将DynamicQuery作为参数。可以从Scala访问此重载。
您知道从Scala调用Java接口的eq(Object)方法的任何方法吗?
使用的Scala版本是2.8.1
答案 0 :(得分:5)
有趣的问题:我之前没见过这个。我不知道如何在Scala中解决它,或者甚至根本不可能解决它。但是,在这种情况下,您可以做的最好的事情是在Java中创建一个包装器。例如:
public class Eq {
static public String eq(I obj, Object that) {
return obj.eq(that);
}
然后,您只需拨打Eq.eq(x, y)
而不是x.eq(y)
。
答案 1 :(得分:3)
你可以通过反思来做到这一点,但我不知道这是不是你想要的,因为它有点难看。
FWIW,您可以通过以下方式完成:
i.getClass().getMethod("eq", classOf[Object]).invoke(i, "a").asInstanceOf[String]
答案 2 :(得分:1)
我不能抓住一切,因为它似乎太明显了。如果(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
)