3

以下を考えると、間違っていないように見える方法でこれを行う方法を見つけるのに苦労しています

public interface IType {}
public interface IMode {}

public interface Factory<T extends IType> {
   IMode get(T o);

   Class<T> getIType();
} 

上記のインターフェースと、対応するファクトリーの両方ITypeを実装するクラスの大きなリストがあります。IMode

たとえば、あるものから別のものに変換できる必要があります。

public class A implements IType {}
public class One implements IMode {}

public class AToOne implements Factory<A> {
    public IMode get(A o){
       return new One();
    }

    public Class<A> getIType(){
       return A.class;
    }
}

これらのクラスの 1 対 1 のマッピングがある場合、つまり、すべての具象に対して、対応するファクトリを持つIType具象が 1 つだけ存在する場合、 s のリストを s のリストに変換するにはどうすればよいでしょうか?IModeITypeIMode

すなわち。

private List<Factory<? extends IType>> factoryList;

public List<IMode> getConversions(List<? extends IType> types){
    ???
}

初めての試みはうまくいかなかったので、

//Fill this using the getIType() method from each factory
Map<Class<IType>, Factory<? extends IType>> factoryList = new HashMap<Class<IType>, Factory<? extends IType>>();

 public List<IMode> getConversions(List<IType> types){
    List<IMode> modes = new ArrayList<IMode>();

    for(IType type : types){
        //Derp
        Factory<? extends IType> factory = factoryList.get(type.getClass());
        //Error
        factory.get(factory.getIType().cast(type));
    }
}

エラー:

 The method get(capture#12-of ? extends IType) in the type
 Factory<capture#12-of ? extends IType>
 is not applicable for the arguments (capture#14-of ? extends IType)
4

2 に答える 2

2

私のコメントで述べたように、マップにアクセスするには、ジェネリック ヘルパー メソッドを使用する必要があります。これは、渡されたものの型と一致する場所Factory<? extends IType>への未チェックのキャストを実行します。Factory<T>T

Map<Class<? extends IType>, Factory<? extends IType>> factoryList =
        new HashMap<Class<? extends IType>, Factory<? extends IType>>();

private <T extends IType> IMode convert(T iType) {
    //unchecked cast - implementation must guarantee map holds correct data
    Factory<T> factory = (Factory<T>)factoryList.get(iType.getClass());
    //then convert
    return factory.get(iType);
}

このヘルパー メソッドをループから呼び出すことができます。

public List<IMode> getConversions(List<IType> types) {
    List<IMode> modes = new ArrayList<IMode>(types.size());
    for (IType type : types) {
        IMode iMode = convert(type);
        modes.add(iMode);
    }
    return modes;
}
于 2012-06-08T05:19:33.187 に答える
1

簡単な解決策は次のとおりです。

interface IFoo {
}

interface IBar {
}

private static class Foo implements IFoo {
}

private static class Bar implements IBar {
}

interface IFoo2IBarConverter<B extends IBar, F extends IFoo> {
    B convert(F foo);
}

private static class Foo2BarConverter implements IFoo2IBarConverter<Bar, Foo> {
    public Bar convert(Foo foo) {
        return new Bar();
    }
}

private static class IFoo2IBarFactory {
    private static HashMap<Class<? extends IFoo>, IFoo2IBarConverter<? extends IBar, ? extends IFoo>> converters = new HashMap<>();

    static {
        converters.put(Foo.class, new Foo2BarConverter());
    }

    public static<F extends IFoo, B extends IBar> B convert(F foo) {
        // ugly unchecked cast here
        IFoo2IBarConverter<B, F> converter = (IFoo2IBarConverter<B, F>) converters.get(foo.getClass());
        return converter.convert(foo);
    }
}


public static void main(String[] args) {
    Foo foo = new Foo();
    IBar bar = IFoo2IBarFactory.convert(foo);
}

IFooサブタイプである特定のクラスをコンバーターインターフェイスにマップするHashMapを取得するだけです。コンバーターはインスタンスを取得し、それを実際に必要な特定のクラスにIFoo変換します。IBar悲しいことに、私たちは醜いキャストを受け入れ、IFoo2IBarFactory.convert()それを回避する方法はないと思います。それでも、少なくとも1つのローカライズされた位置にあり、適切なコメントとSuppressWarningがあれば、それと一緒に暮らせると思います。

于 2012-06-07T21:41:37.347 に答える