如何将一个接口上的实现者转换为另一个接口?

时间:2012-06-07 21:12:39

标签: java generics

考虑到以下内容,我很难找到一种方法来做到这一点似乎没有错误

public interface IType {}
public interface IMode {}

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

   Class<T> getIType();
} 

我有上面的接口和一个关于类ITypeIMode以及相应工厂的类的大型列表。

我需要能够从一个转换为另一个,例如,

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,只有一个具有相应工厂的具体IMode我如何将IType的列表转换为IMode的列表?

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)

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分: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,你可以忍受它,我想