2012-07-30 11 views
7

スカラ(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> 

しかし、私は...

Javaインタフェースのメソッドを失敗していますしかし、これはコンパイルされません。

[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

+1

'Key 'の仕組みを知る必要があります。私が 'public interface Key 'を使用すると、上のコードがうまくコンパイルされるからです。 –

+0

@GarfieldKlonどのスカラのバージョンで作業していますか? –

+0

@ 0__どのバージョンでコンパイルしますか? –

答えて

4

コンパイラがsetAttributeLocalへの通話に不満で表示されます。 setAttributeLocalにはKey[Number]が必要ですが、Key[_ <: T]を提供しています。 Java-Landでは、Key<? extends Number>Key<Number>として渡すことを意味しています。

提案は、JavaまたはScalaで定義されているかどうかによって、setAttributeLocalKey<? extends Number>またはKey[_ <: Number]を受け入れることです。

+0

@GarfieldKlon私はこれを数回読まなければなりませんでした。ベンが示唆していることは、あなたが 'setAttribute'を修正することに集中しているなら、間違ったことを見ているかもしれないと思います。あなたが記述したエラーは、 'setAttribute'ではなく、' setLocalAttribute'の型問題です。 'setLocalAttribute'の定義はどのように見えますか? –

+0

@リチャード - これは私がこれを再現できなかった理由を説明しています –

+0

最終的にこのソリューションを追加しました: 'private def setAttributeLocal [T](key:Key [T]、value:Object)' – GarfieldKlon

1

ここから少し外れています。

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

をキーの型Tを保持するために悪い/奇妙なようだが、値には使用しない:

は、あなたがしようとしています。私の推測では、それはあなたが不変のエラーを取得している場所です。タイプNumberの値をTのキーに設定しようとしていて、のNumberNumberの場合はTを渡すことができるとわかっています)を渡すことができないかどうかは不明です。

もっとコードを表示できますか?

+0

これはオプションではありません。オーバーライドではありません。 – GarfieldKlon

+0

JavaとScalaの型インタフェースには制限があります。あなたがJavaでやっていることは、タイプが悪いので、Scalaはそれを認めません。 このタイプのウィザードを引き続き使用したい場合は、Javaのタイプシステムを使用する必要があります。 – jsuereth

1

@jsuerethは既に前者はKey[T <: Number]を受け入れるが、後者であるのに対し、正確Numberされるキーで行く値を固定すること、即ち、setAttributesetAttributeLocalの署名の間に不一致がある、指摘したようにより柔軟で、キーと値をT <: Numberにすることができます。これはむしろ奇妙に見え、その決定を再検討したいかもしれません。 @Ben Schulzによって説明された問題にもつながります。

いずれにしても、コンパイラ(2.9。

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. */ 
    } 
} 
)以下のセットアップに満足しています
関連する問題