我有这种情况,我试图创建它的一个例子,并希望看看是否有任何优雅的方法来解决它。
假设我有一些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>>
然后我收到了很多警告。
答案 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类中。如果每种类型只有一个转换器,那就更好了。