使用 arg Class<?> 覆盖 Java 方法在斯卡拉 [英] Override Java method with arg Class<?> in Scala
问题描述
我正在尝试从无法更改的外部库中子类化一个类 (Y).它有一个这样的方法:
I am trying to subclass a class (Y) from an external library that can not be changed. It has a method as such:
protected Object doSomething(Class<?> clazz)
现在在我的 Scala 类 (X) 中,我正在扩展这个类并尝试覆盖该方法.
Now in my Scala class (X) I am extending this class and trying to override the method.
override protected def doSomething(clazz: Class[_ <: Object]): AnyRef
然而,这会导致方法 doSomething 不覆盖任何内容".将代码更改为:
However this results in 'Method doSomething overrides nothing'. Changing the code to:
override protected def doSomething(clazz: Class[_]): AnyRef
停止此错误,但现在编译该类时会导致以下错误:
Stops this error but now when the class is compiled it results in the following error:
class X needs to be abstract, since method doSomething in class Y of type (x$1: Class[_ <: Object])Object is not defined
(Note that Class[_ <: T] does not match Class[_]: their type parameters differ)
有什么办法可以做到这一点吗?Scala 版本:2.12.1,Java 版本 8.
Is there any way to achieve this? Scala Version: 2.12.1, Java Version 8.
推荐答案
在问题中你没有提到 Object doSomething(Class<?> clazz)
方法是 的实现抽象 T doSomething(Class extends T> clazz)
抽象泛型类的方法.
In the question you did not mention that Object doSomething(Class<?> clazz)
method is the implementation of abstract T doSomething(Class<? extends T> clazz)
method of abstract generic class.
所以实际上您有以下 Java 类(为了简洁起见,我将 doSomething
重命名为 test
):
So actually you have following Java classes (I renamed doSomething
to test
for brevity):
public abstract class AbstractJava<T> {
protected abstract T test(Class<? extends T> c);
}
public class ConcreteJava extends AbstractJava<Object> {
@Override
protected Object test(Class<?> c) {
return null;
}
}
并且您正在尝试实现以下 Scala 类:
And you are trying to implement following Scala class:
class ConcreteScala extends ConcreteJava {
override protected def test(c: Class[_]) = super.test(c)
}
但是编译失败,因为当你尝试覆盖 test()
Scala 处理 ConcreteJava.test()
和 AbstractJava.test()
方法好像他们有不同的签名.
But compilation fails because when you try to override test()
Scala treats ConcreteJava.test()
and AbstractJava.test()
methods as if they have different signature.
我找到了以下解决方法.
I found the following workaround.
创建额外的 Java 类,通过覆盖 test()
将其重命名"为 renameTest()
并提供调用超级 ConcreteJava.test() 的能力
通过 concreteTest()
方法.
Create additional Java class that by overriding test()
"renames" it to renameTest()
and also provides ability to call super ConcreteJava.test()
through concreteTest()
method.
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()
方法.
Now in ConcreteScala
class you can override renameTest()
and you're still able to call super ConcreteJava.test()
method using concreteTest()
method.
class ConcreteScala extends RenameJava {
override protected def renameTest(c: Class[_]) = {
// custom logic
concreteTest(c)
}
}
在您特定的Spring"案例中,它是通过以下方式实现的.
In your specific "Spring" case it's implemented in the following way.
重命名GsonHttpMessageConverter.java
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.json.GsonHttpMessageConverter;
import java.io.IOException;
public abstract class RenameGsonHttpMessageConverter extends GsonHttpMessageConverter {
protected Object superReadInternal(Class<?> clazz, HttpInputMessage inputMessage) throws
IOException, HttpMessageNotReadableException {
return super.readInternal(clazz, inputMessage);
}
abstract protected Object renameReadInternal(Class<?> clazz, HttpInputMessage inputMessage) throws
IOException, HttpMessageNotReadableException;
@Override
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
return renameReadInternal(clazz, inputMessage);
}
}
CustomGsonHttpMessageConverter.scala
import org.springframework.http.HttpInputMessage
class CustomGsonHttpMessageConverter extends RenameGsonHttpMessageConverter {
override protected def renameReadInternal(clazz: Class[_], inputMessage: HttpInputMessage) = {
// custom logic
// or you may want to call
superReadInternal(clazz, inputMessage)
}
}
我还做了一个错误报告 SI-10155.
Also I made a bug report SI-10155.
这篇关于使用 arg Class<?> 覆盖 Java 方法在斯卡拉的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!