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;
    }
}

鉴于这些类是一对一的映射,即对于每个具体IType都有一个且只有一个IMode具有相应工厂的具体,我将如何将 s 列表转换为ITypes 列表IMode

IE。

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);
}

您只需使用一个 HashMap ,它将作为某个转换器接口的子类型的特定类映射IFoo到某个转换器接口。转换器获取IFoo实例并将其转换为IBar.. 实际上转换为我们想要的特定类。可悲的是,我们得到了一个丑陋的演员阵容IFoo2IBarFactory.convert(),我认为没有任何办法可以避免这种情况。仍然至少它只是在一个本地化的位置,并且有正确的评论和一个 SuppressWarning 你可以忍受它,我想

于 2012-06-07T21:41:37.347 回答