在Scala中,我需要覆盖以下给定的Java类和方法:
public abstract class AbstractJava<T> {
protected abstract T test(Class<? extends T> clazz);
}
public class ConcreteJava extends AbstractJava<Object> {
@Override
protected Object test(Class<?> clazz) {
return null;
}
}
// Scala
class ConcreteScala extends ConcreteJava {
protected override def test(clazz: Class[_ <: AnyRef]): AnyRef =
super.test(clazz)
}
我收到了编译错误:
error: ambiguous reference to overloaded definition,
both method test in class ConcreteJava of type
(clazz: java.lang.Class[_])java.lang.Object
and method test in class AbstractJava of type
(clazz: java.lang.Class[_ <: java.lang.Object])java.lang.Object
match argument types (Class[_$1]) and expected result type AnyRef
super.test(clazz)
我不希望Scala编译器在abstract
调用时引用super
方法。另外,我希望它首先引用 direct 超类。
如何编译Scala类?
谢谢!
修改
当离开super.test(clazz)
电话时,会出现错误消息:
error: name clash between defined and inherited member:
method test:(clazz: Class[_ <: AnyRef])AnyRef and
method test:(clazz: java.lang.Class[_])java.lang.Object in class ConcreteJava
have same type after erasure: (clazz: java.lang.Class)java.lang.Object
protected override def test(clazz: Class[_ <: AnyRef]): AnyRef = null
嗯,当然这些是相同的类型(或变体)......! - 所以Scala / Java继承有问题......
感谢 michid ,有一个初步的解决方案:
class ConcreteScala3 {
this: ConcreteJava =>
protected override def test(clazz: Class[_ <: AnyRef]): AnyRef = {
this.foo() // method of ConcreteJava
null
}
}
虽然我们无法从此处拨打super
来电。
回应仍然是最受欢迎的。
答案 0 :(得分:5)
使用原始类型覆盖Java方法时存在一些限制。请参阅相应的Scala ticket。特别是Martin Odersky的comment:“[...]在这些情况下,唯一能做的就是在Java中实现一个实现该方法的子类。[...]”
但是,我在blog post早些时候曾指出,某些案件似乎有解决办法。诀窍是使用Java端原始类型的存在类型显式声明重写Scala类的self类型。
通过这种技术,我得到了以下工作:
public abstract class AbstractJava<T> {
protected abstract T test(Class<T> clazz);
}
public class ConcreteJava extends AbstractJava<Object> {
@Override
protected Object test(Class<Object> clazz) {
return null;
}
}
class ConcreteScala extends ConcreteJava {
this: AbstractJava[AnyRef] =>
protected override def test(clazz: Class[AnyRef]): AnyRef = {
super.test(clazz)
}
}
答案 1 :(得分:0)
我认为这肯定是一个错误,我创建了一个问题SI-10155。
您可以应用以下解决方法。
通过覆盖test()
&#34;重命名&#34>创建其他Java类。它可以renameTest()
,还可以通过ConcreteJava.test()
方法调用超级concreteTest()
。
public abstract class RenameJava extends ConcreteJava {
public Object concreteTest(Class<?> c) {
return super.test(c);
}
abstract protected Object renameTest(Class<?> c);
@Override
protected Object test(Class<?> c) {
return renameTest(c);
}
}
现在在ConcreteScala
课程中,您可以覆盖renameTest()
,并且仍然可以使用ConcreteJava.test()
方法调用超级concreteTest()
方法。
class ConcreteScala extends RenameJava {
override protected def renameTest(c: Class[_]) = {
// custom logic
concreteTest(c)
}
}