[英]How can i make this work with java generics
假设我有这个接口和混凝土:
public interface MeterValue {}
public class MeterValueA implements MeterValue {}
public class MeterValueB implements MeterValue {}
public interface ReportBuilder<T extends MeterValue> {}
public class ReportBuilderA implements ReportBuilder<MeterValueA> {}
public class ReportBuilderB implements ReportBuilder<MeterValueB> {}
我有一个全局实例:
ReportBuilder<MeterValue> reportBuilder;
我想改变reportBuilder实例,如下所示:
if (isA())
reportBuilder = new ReportBuilderA();
else
reportBuilder = new ReportBuilderB();
reportBuilder.desiredMethod();
这样做我得到“Type Missmatch”。 我怎样才能获得所需的功能? 或者我怎样才能提高课堂设计的灵活性?
编辑:
通配符? 解决了这个问题。 但也介绍了其他问题。 假设我在界面中有这个方法:
public interface ReportBuilder<T extends MeterValue> {
public String getStuff(List<T> values);
}
public class ReportBuilderA implements ReportBuilder<MeterValueA> {
@Override
public String getStuff(List<MeterValueA> values) { return "A"; }
}
public class ReportBuilderB implements ReportBuilder<MeterValueB> {
@Override
public String getStuff(List<MeterValueB> values) { return "B"; }
}
说我有这个实例:
ReportBuilder<? extends MeterValue> reportBuilder = new ReportBuilderA();
和:
List<? extends MeterValue> list = new ArrayList<MeterValueA>();
String s = reportBuilder.getStuff(list);
由于列表包含通配符,因此对getStuff(...)的调用将不起作用。 一个修复方法是将ReportBuilder接口方法修改为:
public String getStuff(List<? extends MeterValue> values);
但后来我打破了具体的ReportBuilders。 (列表也是一个内容可能不同的全局实例)
有任何想法吗?
我认为你应该将报告构建器变量声明为:
ReportBuilder<? extends MeterValue> reportBuilder;
这允许reportBuilder
具有任何ReportBuilder
类,具有泛型类型的MeterValue
,或任何实现该接口的类。
顺便说一句,如果您已经不熟悉它,创建ReportBuilder
实例似乎与工厂方法模式类似,可能值得阅读它。 (当然还有其他模式。)
public interface MeterValue {}
public class MeterValueA implements MeterValue {}
public class MeterValueB implements MeterValue {}
public interface ReportBuilder<T extends MeterValue> {
void desiredMethod();
}
public class ReportBuilderA implements ReportBuilder<MeterValueA> {
@Override
public void desiredMethod() {}
}
public class ReportBuilderB implements ReportBuilder<MeterValueB> {
@Override
public void desiredMethod() {}
}
void f() {
ReportBuilder<? extends MeterValue> reportBuilder = null;
if (Math.random() > 0.5)
reportBuilder = new ReportBuilderA();
else
reportBuilder = new ReportBuilderB();
reportBuilder.desiredMethod();
}
哪里: ReportBuilder<? extends MeterValue>
ReportBuilder<? extends MeterValue>
表示泛型参数可以扩展MeterValue接口。
请参阅教程以阅读有关通配符声明的更多说明。
注意:请在特定情况下查看此代码,以避免并行继承气味。 如果要添加一些新的MeterValue,你应该添加ReportBuilder它应该意味着你可能有这个问题。
编辑:
您不能将具有MeterValue子类型的数组传递给ReportBuilderA,它至少会重新记录MeterValueA。 它不是类型安全的技术。 继承后实例化具体类更适合C ++。 在Java中,最好不要在继承后更改受限类型。
可能的解决方案,可能适用于您的具体案例:
1)为MeterValue使用单个接口。 所有差异都转移到ReportBuilder继承。 这意味着您在项目中具有并行继承。
2)调用getStuff()
方法时使用具体的List<MeterValueA>
。 处理List<MeterValueA>
和List<MeterValueB>
所有共享逻辑都移动到带签名的方法: public void sharedLogic(List<? extends MeterValue> list)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.