Java泛型和类层次结构
我有这种情况,我试图创建一个例子,并想看看是否有任何优雅的方式来解决它 假设我有一些可显示的接口和实现类:Person和Car,并且我有如下声明的通用转换器类:Java泛型和类层次结构,java,generics,Java,Generics,我有这种情况,我试图创建一个例子,并想看看是否有任何优雅的方式来解决它 假设我有一些可显示的接口和实现类:Person和Car,并且我有如下声明的通用转换器类: public interface Converter<T extends Displayable> { boolean canConvert(Displayable o); String convert(T o); T decode(String s); boolean canRevert(S
public interface Converter<T extends Displayable> {
boolean canConvert(Displayable o);
String convert(T o);
T decode(String s);
boolean canRevert(String s);
}
公共接口转换器{
布尔转换(可显示o);
字符串转换;
T解码(字符串s);
布尔值(字符串s);
}
假设我有这个的实现
public class CarConverter implements Converter<Car> { ... }
公共类CarConverter实现转换器{…}
及
公共类PersonConverter实现转换器{…}
现在在我的使用中,我有一个可显示列表和一个转换器列表,我想转换和还原可显示列表:
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 ds=new ArrayList();
ds.增补(新人士(“ma”,12));
ds.添加(新人员(“fa”,43));
ds.添加(新车());
ds.添加(新车());
ds.添加(新人员(“Sol”,58));
Listcs=newarraylist();
添加(新的CarConverter());
添加(新PersonConverter());
ArrayList displays=新建ArrayList();
用于(可显示的d:ds){
用于(转换器c:cs){
如果(c.canConvert(d)){
显示。添加(c.convert(d));
打破
}
}
}
List ret=new ArrayList();
用于(字符串显示:显示){
用于(转换器c:cs){
如果(c.canRevert(显示)){
可显示d=c.解码(显示);
再加上(d);
}
}
}
令人恼火的是,我不得不声明一个列表转换器,失去了泛型
List<Converter>
列表
如果我试图声明,就会出现语法错误
List<Convert<Displayable>>
列表
然后我收到了很多警告。看起来转换器只是在对可显示内容进行字符串表示。如果是这样的话,我认为您真正想要做的是为每个displaybable重写toString()方法,并为每个displaybable提供一个以display字符串作为参数的构造函数。这样,您就不必担心为每个Displayable的实现实现一个单独的转换器。所以一个人看起来像:
public class Person implements Displayable {
public Person(String display) {
// Make a Person from a display
}
public String toString() {
// Make a display from a person
}
...
}
您可以这样做,只需对列表声明稍作更改:
List<Converter<? extends Displayable>> list = ...
List这可能很蹩脚,但在这种情况下根本不需要泛型。因为您已经使用了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 interface Converter {
boolean canConvert(Displayable o);
String convert(Displayable o);
Displayable decode(String s);
boolean canRevert(String s);
}
或者我缺少的泛型有什么优势?
一个更漂亮的解决方案是在可显示类中包含转换器代码。如果你对每种类型只有一个转换器,那就更好了。为什么你认为列表不如列表那么具体?你有接口名转换器而不是转换器。你可以声明“代码>列表> Cs = NealAlyList > <代码>,但是你必须担心<代码>捕获< /Cord>。只是为了解释这个问题,我在现实生活中的用法要复杂得多,泛型在这种情况下非常有用。罗布的回答是最优雅的,他应该考虑到这一点。我也尝试了罗布的解决方案,但失败了。示例代码仍然给我滥用泛型的感觉,但我相信您的实际使用有很好的理由。明天我得再试试罗布的解决方案,我忘了一些小事。
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);
}