在Scala中使用arg Class <! - ? - >覆盖Java方法

时间:2017-01-14 11:16:21

标签: scala

我正在尝试从无法更改的外部库中继承类(Y)。它有一个方法:

protected Object doSomething(Class<?> clazz)

现在在我的Scala类(X)中,我正在扩展此类并尝试覆盖该方法。

override protected def doSomething(clazz: Class[_ <: Object]): AnyRef

然而,这会导致&#39; Method doSomething覆盖任何内容&#39;。将代码更改为:

override protected def doSomething(clazz: Class[_]): AnyRef

停止此错误,但现在编译类时会导致以下错误:

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.

1 个答案:

答案 0 :(得分:2)

在这个问题中你没有提到Object doSomething(Class<?> clazz)方法是抽象泛型类的abstract T doSomething(Class<? extends T> clazz)方法的实现。

所以实际上你有以下Java类(为简洁我将doSomething重命名为test):

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类:

class ConcreteScala extends ConcreteJava {
    override protected def test(c: Class[_]) = super.test(c)
}

但编译失败,因为当您尝试覆盖test()时,Scala会将ConcreteJava.test()AbstractJava.test()方法视为具有不同的签名。

我找到了以下解决方法。

创建其他Java类,通过覆盖test()“将其”重命名为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)
  }
}

在您特定的“Spring”案例中,它以下列方式实现。

<强> RenameGsonHttpMessageConverter.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