2012-02-08 8 views
5

のJavaジェネリック抽象工場の問題、私はこの仕事にするために苦労しています

if (msgIn.isMyMapper()) 
      return new MyTaskMapperFactory(); 

どれ:ここに私のMapperFactoryで

Type mismatch: cannot convert from MapperFactory.MyTaskMapperFactory to MapperFactory

public abstract class MapperFactory<M extends TaskMapper<? extends Message, ? extends Message, ? extends TaskForm>> { 

    public static <M extends TaskMapper<? extends Message, ? extends Message, ? extends TaskForm>> MapperFactory<M> getMapperFactory(Message msgIn, Message msgOut) { 

     if (msgIn.isMyMapper()) 
      return new MyTaskMapperFactory(); 

     throw new IllegalStateException("Mapper not found!"); 
    } 

    public abstract TaskMapper<? extends Message, ? extends Message, ? extends TaskForm> getTaskMapper(); 

    public static class MyTaskMapperFactory extends MapperFactory<MyTaskMapper> { 

     @Override 
     public TaskMapper<? extends Message, ? extends Message, ? extends TaskForm> getTaskMapper() { 
      return new MyTaskMapper(); 
     } 

    } 
} 

public interface TaskMapper<I extends Message, O extends Message, F extends TaskForm> { 

    public F fillForm(I msgIn, O msgOut, F taskForm); 

    public O fillMsgOut(F taskForm); 
} 

public class MyTaskMapper implements TaskMapper<IncomingMessage, OutgoingMessage, MyTaskForm > { 

    public MyTaskForm fillForm(IncomingMessage msgIn, OutgoingMessage msgOut, 
      MyTaskForm taskForm) { 
     return null; 
    } 

    public OutgoingMessage fillMsgOut(MyTaskForm taskForm) { 
     return null; 
    } 

} 

問題は、コンパイル・エラーがあるがどのようにこのエラーを修正するアイデア?

public static <M extends TaskMapper<? extends Message, ? extends Message, ? extends TaskForm>> MapperFactory<M> getMapperFactory(Message msgIn, Message msgOut) { 

     if (msgIn.isMyMapper()) 
      return new MyTaskMapperFactory(); 

     throw new IllegalStateException("Mapper not found!"); 
    } 

をして:置き換えもちろん

public static MapperFactory<?> getMapperFactory(Message msgIn, Message msgOut) { 

     if (msgIn.isMyMapper()) 
      return new MyTaskMapperFactory(); 

     throw new IllegalStateException("Mapper not found!"); 
    } 

は動作しますが、それは私が探しています答えではありません。

これは、一般的な抽象的な工場パターンの一般的な問題です。 カスタムメイドアップオブジェクトを使用してソースサンプルを提供する回答も歓迎されます。

+0

'MAPPER'は、Javaの規約に準拠したクラス名ではありません。 –

+0

クラス名は可能な限り小さくしてください(ただし、まだクリアしてください)。そして、 'MAPPER'を' Mapper'に改名しますか?奇妙な/長いクラス名はちょうど質問を混乱させ/混乱させます*と*答え。 – Bohemian

+0

@his MAPPERはクラス名ではありません。 HashMapのTなどの汎用型の名前です

答えて

4

効果的なJavaの、第2版、項目28によると:

If a type parameter appears only once in a method declaration, replace it with a wildcard.

あなたgetMapperFactoryメソッドは戻り値の型で型パラメータMを使用しています。このアドバイスに従うこと、次のメソッドシグネチャを与え、この方法は、コンパイルされます。

public static MapperFactory<? extends TaskMapper<Message, ? extends Message, ? extends String>> getMapperFactory(Message msgIn, Message msgOut) 

編集:より多くの私はコードを見て、より多くの私はMapperFactoryがパラメータ化されるべきではないと思います。パラメータがここのコードで使用されていない場合、getTaskMapperはTaskMapperを返します。

abstract class MapperFactory<M extends TaskMapper<?, ?, ?>> { 

    public static MapperFactory<?> getMapperFactory(Message msgIn, Message msgOut) { 
     if (msgIn.isMyMapper()) return new MyTaskMapperFactory(); 
     throw new IllegalStateException("Mapper not found!"); 
    } 

    public abstract M getTaskMapper(); 
} 


class MyTaskMapperFactory extends MapperFactory<MyTaskMapper> { 

    @Override 
    public MyTaskMapper getTaskMapper() { 
     return new MyTaskMapper(); 
    } 

} 


interface TaskMapper<I extends Message, O extends Message, F extends TaskForm> { 

    public F fillForm(I msgIn, O msgOut, F taskForm); 

    public O fillMsgOut(F taskForm); 

} 

class MyTaskMapper implements TaskMapper<IncomingMessage, OutgoingMessage, MyTaskForm> { 

    public MyTaskForm fillForm(IncomingMessage msgIn, OutgoingMessage msgOut, MyTaskForm taskForm) { 
     return null; 
    } 

    public OutgoingMessage fillMsgOut(MyTaskForm taskForm) { 
     return null; 
    } 

} 

それはあなたがいない場合、それを使用するすべての方法では、クラスの型パラメータを繰り返す本当に必要はありません。私のソリューションは、火でできるだけジェネリック医薬品の多くを殺すことになる

+2

さらに短くても、署名は 'public static MapperFactory getMapperFactory()'にすることができます。このメソッドは、 'MapperFactory'のクラスシグネチャよりも型パラメータを制限しません。 'public abstract TaskMapper getTaskMapper()'も同じです。 (これは 'public abstract M getTaskMapper()'でも可能ですが、型パラメータの背後にあるインテントが何であるかを知ることはできません)*疑わしいときはジェネリックスを少なくしてください*はおそらく大体の目安です。 – millimoose

1

return文は、型キャストで正常に動作します:msgInはおそらくBpm007PrepareDocTaskMapperのインスタンスすることはできませんのでBpm007PrepareDocTaskMapperは、BpmCommonMessageDtoを拡張していないため

return (BpmMapperFactory<MAPPER>)new Bpm007PrepareDocTaskMapperFactory(); 

このコードは、現在の形にかかわらず、実行することはありません。

+0

私は 'if'の部分を編集しました。情報はまだありませんでしたが、ここでは関係ありません。 キャストを避ける方法はありますか? –

1

本当に自分が何であるかを気にしたり、クラスの署名よりも多くのことを拘束する必要はありません。

関連する問題