2011-10-26 16 views
2

if/elseを使用する代わりに、マップを使用して具体的な実装をしたいと考えています。"extends"を持つJavaジェネリックス

特定のエンティティハンドラを宣言するためにジェネリックを使用したいのですが、特定のエンティティを処理する魔法使いですが、ハンドラが自分のエンティティインターフェイスの拡張機能を受け入れるという問題があります。コードは次のようになります。

private Map<Class<IEntity>, IEntityHandler> handlers; 

public void callingMethod(IModel model) { 
    for (IEntity entity : model.getObjects()) { 
    // handle accepts just IDevice and not IEntity ! 
    handlers.get(entity).handle(entity); 
    } 
} 

public interface IEntityHandler<T extends IEntity> { 
    handle(T entity); 
} 

public class DeviceHandler implements IEntityHandler<IDevice> { 
    @Override 
    public void handle(IDevice deviceEntity) { 
    // do something 
    } 
} 

IEntityの処理方法はどのようにして取得できますか? IDeviceはIEntityから拡張されています。

答えて

1

あなたのようにマッピング宣言:

Map<Class<T extends IEntity>, IEntityHandler> handlers. 
+1

マップにフィールドを持つクラスに型パラメータ 'T'があるとは思いません。マップはさまざまなクラスのハンドラを含むことができるため、これは不可能です。それがすべての目的です。 –

+0

それは動作します!ありがとう! – myborobudur

0
private Map<? extends IEntity, ? extends IEntityHandler> handlers; 
+0

彼は 'Class'オブジェクトをハンドラにマップする必要があります。ハンドラには' IEntity'のインスタンスではありません。 –

+0

ここで私はこのビルドエラーを取得します:IEntityHandler <キャプチャ#1-of?のメソッドハンドル(キャプチャ#1-?IEntityを拡張)? extends IEntity>は引数には適用されません(IEntity) – myborobudur

0
private Map<Class<? extends IEntity>, ? extends IEntityHandler> handlers; 
+1

実際にマップにハンドラを配置しようとすると問題が発生します。 '?コレクション宣言の型paramのための拡張は、通常、理由を理由にコレクションにエントリを直接追加しようとするとうまくいかない(http://download.oracle.com/javase/tutorial /java/generics/wildcards.html)。 –

+0

はい、あなたは正しいです。 ITはちょうどIEntityHandlerでなければなりません – Mikel

+0

ビルドエラーと同じです:IEntityHandler <キャプチャ#1-of?タイプのメソッドハンドル(キャプチャ#1??IEntity)?拡張IEntity>は引数には適用されません(IEntity) – myborobudur

1

まず第一に、あなたはこの行を変更する必要があります...これに

handlers.get(entity).handle(entity); 

...

handlers.get(entity.getClass()).handle(entity); 

次に、他の人が言ったように、具体的なクラスをハンドラにマップしたいので、マップのClass<IEntity>型パラメータをClass<? extends IEntity>に変更することをお勧めします。

このようにすれば、エラーは発生しません。マップ内のIEntityHandlerタイプのパラメータが生のタイプであるため、警告のみです。しかし、それを? extends IEntityHandlerまたはIEntityHandler<? extends IEntity>に変更しようとすると、マップの割り当てまたは移入時にコンパイルエラーが発生します。

これを変更するには(getClass()Class<? extends IEntity>)、単にアノテーション付きの警告を抑制することをお勧めします。適切なクラスの適切なハンドラがマップに適切に配置されている限り、問題は発生しません。

+0

あなたは絶対に正しいです!あなたの詳細な説明をありがとう。 – myborobudur

0

あなたが向かっているのは、(深呼吸)typesafe hetereogeneous containerです。ただし、保存するオブジェクトは汎用オブジェクトなので、super type tokensを使用する必要があります。

私はあなたが紹介してから、このようなトップループを書き換えることで、ワイルドカードを飼いならすために必要があると思う:

for (IEntity entity: model.getObjects()) { 
    handle(entity); 
} 

private <T extends IEntity> handle(T entity) { 
    IEntityHandler<T> handler = ... get appropriate handler from THC ... 
    handler.handle(entity); 
} 

私も、このことについてはよく分かりません。これはかなり大まかなスケッチです。

関連する問題