Scala:覆盖通用Java方法II [英] Scala: Overriding Generic Java Methods II

查看:169
本文介绍了Scala:覆盖通用Java方法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屋!

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