Java泛型和类层次结构

时间:2011-06-23 10:27:17

标签: java generics

我有这种情况,我试图创建它的一个例子,并希望看看是否有任何优雅的方法来解决它。

假设我有一些Interface Displayable,并实现了Classes:Person和Car,我有这样的通用Converter类:

public interface Converter<T extends Displayable> {
    boolean canConvert(Displayable o);
    String convert(T o);
    T decode(String s);
    boolean canRevert(String s);
}

假设我有此实现

public class CarConverter implements Converter<Car> { ... }

public class PersonConverter implements Converter<Person> { ... }

现在在我的用法中我有一个Displayable列表和一个转换器列表,我想转换并还原Displayables:

List<Displayable> ds = new ArrayList<Displayable>();
ds.add(new Person("ma",12));
ds.add(new Person("fa",43));
ds.add(new Car());
ds.add(new Car());
ds.add(new Person("Sol",58));

List<Converter>cs = new ArrayList<Converter>();
cs.add(new CarConverter());
cs.add(new PersonConverter());

        ArrayList<String> displays = new ArrayList<String>();
        for(Displayable d:ds) {
            for(Converter c:cs) {
                if(c.canConvert(d)) {
                    displays.add(c.convert(d));
                    break;
                }
            }
        }

        List<Displayable> ret = new ArrayList<Displayable>();

        for(String display : displays) {
            for(Converter c:cs) {
                if(c.canRevert(display)) {
                    Displayable d = c.decode(display);
                    ret.add(d);
                }                
            }
        }
令人讨厌的是,我必须声明一个转换器列表,丢失泛型。

List<Converter>

如果我尝试声明

,我会收到语法错误
List<Convert<Displayable>>

然后我收到了很多警告。

3 个答案:

答案 0 :(得分:2)

您可以这样做,只需对列表声明稍作修改即可:

List<Converter<? extends Displayable>> list = ...

这对你有用。这里要记住的关键是,您不能依赖嵌套类型参数中的继承,您需要使用extends声明扩展名。

如果您有List<Converter<Displayable>>,则可以将Converter<Displayable>个实例添加到该列表,而不是Converter<SomethingThatExtendsDisplayable>>

答案 1 :(得分:0)

看起来转换器只是对可显示的字符串表示。如果是这种情况,我认为你真正想做的是为每个Displayable覆盖toString()方法,并为每个Displayable提供一个以显示字符串作为参数的构造函数。然后,您不必担心为Displayable的每个实现实现单独的Converter。所以一个人看起来像:

public class Person implements Displayable {
    public Person(String display) {
        // Make a Person from a display
    }

    public String toString() {
        // Make a display from a person
    }

    ...
}

答案 2 :(得分:0)

这可能很蹩脚,但在这种情况下你根本不需要泛型。由于您已经使用了canConvert和canRevert,因此不需要额外的编译时类型检查。

我的快速修复代码:

public static void main(String[] args) {
    List<Displayable> ds = new ArrayList<Displayable>();
    ds.add(new Person("ma", 12));
    ds.add(new Person("fa", 43));
    ds.add(new Car());
    ds.add(new Car());
    ds.add(new Person("Sol", 58));

    ArrayList<Converter> cs = new ArrayList<Converter>();
    cs.add(new CarConverter());
    cs.add(new PersonConverter());

    ArrayList<String> displays = new ArrayList<String>();
    for (Displayable d : ds) {
        for (Converter c : cs) {
            if (c.canConvert(d)) {
                displays.add(c.convert(d));
                break;
            }
        }
    }

    List<Displayable> ret = new ArrayList<Displayable>();

    for (String display : displays) {
        for (Converter c : cs) {
            if (c.canRevert(display)) {
                Displayable d = c.decode(display);
                ret.add(d);
            }
        }
    }
}

public class CarConverter implements Converter {

    @Override
    public boolean canConvert(Displayable o) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean canRevert(String s) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public String convert(Displayable o) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Car decode(String s) {
        // TODO Auto-generated method stub
        return null;
    }

}

包转换;

public interface Converter {
    boolean canConvert(Displayable o);
    String convert(Displayable o);
    Displayable decode(String s);
    boolean canRevert(String s);    
}

或者我遗漏的仿制药是否有任何优势? 一个更漂亮的解决方案是将转换器代码包含在Displayable类中。如果每种类型只有一个转换器,那就更好了。

相关问题