使用 arg Class<?> 覆盖 Java 方法在斯卡拉 [英] Override Java method with arg Class&lt;?&gt; in Scala

查看:36
本文介绍了使用 arg Class<?> 覆盖 Java 方法在斯卡拉的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从无法更改的外部库中子类化一个类 (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 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆