Scala:覆盖通用Java方法II [英] Scala: Overriding Generic Java Methods II
问题描述
在Scala中,我需要重写以下给定的Java类和方法:
In Scala, I need to override the following, given, Java classes and methods:
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编译器在super
调用中引用abstract
方法.另外,我希望它首先引用 direct 超级类.
I wouldn't expect the Scala compiler to refer to an abstract
method on a super
call. Also, I'd expect it to refer to the direct super class first.
如何使Scala类编译?
How can I make the Scala class compile?
谢谢!
取消super.test(clazz)
呼叫时,将出现错误消息:
When leaving off the super.test(clazz)
call, there'll be the error message:
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继承有问题...
Well, of course these are the same types (or variants) ...! - So there's something wrong with Scala/Java inheritance ...
由于 michid ,有一个初步的解决方案:
Thanks to michid, there's a preliminary solution:
class ConcreteScala3 {
this: ConcreteJava =>
protected override def test(clazz: Class[_ <: AnyRef]): AnyRef = {
this.foo() // method of ConcreteJava
null
}
}
尽管我们无法从此处进行super
调用.
although we can't make super
calls from here.
仍然非常欢迎您答复.
推荐答案
使用原始类型覆盖Java方法时存在一些限制.请参阅相应的斯卡拉门票.特别是马丁·奥德斯基(Martin Odersky)的
There are some limitations when overriding Java methods with raw types. See the corresponding Scala ticket. Specifically Martin Odersky's comment: "[...] The only thing one can do in these situations is implement a subclass in Java that implements the method. [...]"
但是,我在博客文章中指出早些时候,似乎在某些情况下可以找到解决方案.诀窍是在Java端使用原始类型的现存类型显式声明覆盖的Scala类的自身类型.
However, I pointed out in a blog post earlier that there seems to be a solution for certain cases. The trick is to explicitly declare the self type of the overriding Scala class using an existential type for the raw type on the Java side.
使用这种技术,我可以完成以下工作:
With this technique I got the following working:
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)
}
}
这篇关于Scala:覆盖通用Java方法II的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!