7

scala (2.9.2) でジェネリックを使用する Java メソッドを実装したいと思います。でも失敗してる…

Java インターフェイス メソッド:

public <T extends Number> void setAttribute(Key<T> key, Number value);

そのメソッドを実装したい Scala コード:

def setAttribute[T <: Number](key: Key[T], value: Number) = {
  setAttributeLocal(key, value)  }

private def setAttributeLocal[T](key: Key[T], value: T) = {
  val stringValue = ConvertUtils.convert(value, classOf[String]).asInstanceOf[String]
  session = session + (key.getValue() -> stringValue)
}

キーは次のようになります。

public class Key<T>

しかし、これはコンパイルされません。

[error]  found   : mypackage.Key[T]
[error]  required: mypackage.Key[java.lang.Number]
[error] Note: T <: java.lang.Number, but Java-defined class Key is invariant in type T.
[error] You may wish to investigate a wildcard type such as `_ <: java.lang.Number`. (SLS 3.2.10)
[error]     setAttributeLocal(key, value)

何が問題なのかわかりません。提案/アイデアはありますか?

greez GarfieldKlon

4

3 に答える 3

4

コンパイラが への呼び出しに不満を持っているようsetAttributeLocalです。setAttributeLocalが必要Key[Number]ですが、 を提供していKey[_ <: T]ます。Key<? extends Number>Java-Land では、これは aを として渡そうとしていることを意味しますKey<Number>

Java で定義されているか Scala で定義されているかに応じて、setAttributeLocalacceptKey<? extends Number>またはを使用することをお勧めします。Key[_ <: Number]

于 2012-07-30T14:29:33.807 に答える
1

ここで何かが少しずれているように見えます。

やってみました:

def setAttribute[T <: Number](key: Key[T], value: T) =
  setAttributeLocal(key, value)

キーの型 T を保持するのは奇妙/悪いようですが、値には使用しません。私の推測では、不変エラーが発生している場所です。Numbertype の値を typeのキーに代入しようとしていますがT、コンパイラは for を渡すことができるかどうかを確認できません(ただし、 NumberforをT渡すことができることはわかっています)。TNumber

もっとコードを見ることができますか?

于 2012-07-30T14:55:14.347 に答える
1

@jsuereth が既に指摘したように、 と の署名には矛盾がありますsetAttributesetAttributeLocalつまり、前者は a を受け入れますKey[T <: Number]が、キーに対応する値を正確に a に修正しますがNumber、後者はより柔軟で、キーと値をするT <: Number。これはかなり奇妙に見えるので、その決定を再考することをお勧めします。また、@Ben Schulz によって説明された問題にもつながります。

いずれにせよ、コンパイラ (2.9.1) は次の設定で問題ありません。

MyI.java:

public interface MyI {
  public <T extends Number> void setAttribute(Key<T> key, Number value);
}

Key.java:

public interface Key<T> {
}

Test.scala:

object Test extends App {
  def setAttribute[T <: Number](key: Key[T], value: Number) = {
    setAttributeLocal(key, value)  }

  private def setAttributeLocal[T](key: Key[T], value: Number) = {
    /* Notice that value is now also of type Number. */
  }
}
于 2012-08-02T08:30:04.193 に答える