2011-07-10 24 views
4
でJavaインタフェースの実装とJavaアノテーションを使用して

EDIT:Scalaの

public interface IFace<T> {} 

@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.METHOD}) 
public @interface Anno { 
    Class<? extends IFace> value(); 
} 

:この問題は、次の既存のJavaライブラリ(簡体字)を考えると

Scalaの2.9.1のように解決されているように見えますライブラリには、@Annoと注釈が付けられた1つ以上のメソッドを含むユーザー定義のインターフェイスが必要なメソッドがあります。

私はJavaからScalaに既存のコードを変換しようとしています。既存のコードベースはIFaceの実装が含まれます

public class Impl implements IFace<String> { } 

をそして、私は、ライブラリが使用可能なScalaのクラスを作成しようとしています:

trait Usage 
{ 
    @Anno(classOf[Impl]) 
    def aMethod(): String 
} 

Scalaのコンパイラはこれを拒否:

$ scalac -explaintypes Usage.scala 
Usage.scala:5: error: type mismatch; 
found : java.lang.Class[Impl](classOf[Impl]) 
required: java.lang.Class[_ <: IFace] 
    @Anno(classOf[Impl]) 
      ^
java.lang.Class[Impl](classOf[Impl]) <: java.lang.Class[_ <: IFace]? 
    java.lang.Class[Impl](classOf[Impl]) <: java.lang.Class[?0?0]? 
    java.lang.Class[Impl] <: java.lang.Class[?0?0]? 
     ?0?0 <: Impl? 
     true 
     Impl <: ?0?0? 
     true 
    true 
    true 
    Nothing <: Impl? 
    <notype> <: Impl? 
    false 
    true 
    Impl <: IFace? 
    false 
    java.lang.Class[Impl] <: java.lang.Class[_ <: IFace]? 
    java.lang.Class[Impl] <: java.lang.Class[?0?0]? 
     ?0?0 <: Impl? 
     true 
     Impl <: ?0?0? 
     true 
    true 
    Nothing <: Impl? 
     <notype> <: Impl? 
     false 
    true 
    Impl <: IFace? 
    false 
    false 
false 
one error found 

ImplIFaceに拡張されているとは思われないため、コードを拒否しているようです。これはJava/Scalaの相互運用性の制限ですか、私はScalaでJavaアノテーションの使い方を別々に指定する必要がありますか?

EDIT:

public interface Usage 
{ 
    @Anno(Impl.class) 
    String aMethod(); 
} 

私はScalaで同じことを言うために正しい構文を見つけようとしている:コンパイルUsage元のJavaのバージョンは、のように見えます。

Class<? extends IFace<?>> value(); 

私はコンパイラがIFace[_]ようIFaceを扱わないとIFace[String](したがってImpl)がIFaceを拡張するとは考えていないと仮定することができます

答えて

1

これは、ScalaがJavaとうまく連携しない境界線の1つです。

public interface IFace<T> {} 
// ... 
    Class<? extends IFace> value(); 

この場合、最も一般的に使用されるソリューション - と私はそこのように、あなたはスカラ座での生タイプの相互作用についての質問を見てお勧めします。問題は、ジェネリック医薬品として宣言された型は、生タイプとして後者使用されていることですスタックオーバーフローに関するこのような場合は、Javaでラッパーを記述することです。

これは可能でしょうか。Annoをオーバーライドvalueに互換性のあるタイプの署名で拡張しようとする可能性があります。戻り値の型をClass<? extends Impl>に絞り込んだり、おそらくIFaceでジェネリックを使用するように書き直してください。

+0

この参考文献と、私が先に検索するときに使用していなかったキーワードであった「生の型」を検索していただきありがとうございます。[1]はScalaのバグレポート[2]を参照しているので、Scalaは生の型を理解しておらず、必要としないとMartin Oderskyが言っています。 [1] http://stackoverflow.com/questions/4991671/why-does-scala-complain-about-illegal-inheritance-when-there-are-raw-types-in-the [2] https: //issues.scala-lang.org/browse/SI-1737 –

+0

また、これはScala 2.9.1ではもう問題ではないようです。 –

+0

@Christopher 'getClass'で返された型が返されましたが、ここで違いが出るようなことはありません。 –

2

例はAnno定義にワイルドカードを追加した後にコンパイルします。

+0

残念ながら私は '@ Anno'を定義するライブラリを制御できませんが、少なくとも1つの解決策があることを知っておいてよかったです。 –