15

Scala では、指定された次の Java クラスとメソッドをオーバーライドする必要があります。

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 コンパイラーが呼び出しでabstractメソッドを参照するとは思いません。また、最初に直接スーパークラスsuperを参照することを期待しています。

Scala クラスをコンパイルするにはどうすればよいですか?

ありがとう!

編集:

通話を終了するsuper.test(clazz)と、次のエラー メッセージが表示されます。

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 の継承に何か問題がある...

michidのおかげで、暫定的な解決策があります。

class ConcreteScala3 {
  this: ConcreteJava =>
  protected override def test(clazz: Class[_ <: AnyRef]): AnyRef = {
    this.foo() // method of ConcreteJava
    null
  }
}

ここから電話をかけることはできませんがsuper

返信は引き続き大歓迎です。

4

2 に答える 2

5

Java メソッドを生の型でオーバーライドする場合、いくつかの制限があります。対応するScala チケットを参照してください。具体的には、Martin Odersky のコメント:「[...] このような状況でできる唯一のことは、メソッドを実装する Java でサブクラスを実装することです。[...]」

ただし、以前のブログ投稿で、特定のケースには解決策があるように思われることを指摘しました。その秘訣は、Java 側で raw 型の存在型を使用して、オーバーライドする Scala クラスの self 型を明示的に宣言することです。

この手法を使用して、次の作業を行いました。

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)
    }
}
于 2011-06-22T20:27:02.560 に答える