在我们当前的代码库中,我们具有以下数据结构来在服务层和前端层之间进行通信:
public class BaseView {
private Integer id;
// Other common attributes and getters/setters;
}
public class BarView extends BaseView {
private String name;
private String Description;
// Other attributes for this object and getters/setters;
}
我们还有一些双扩展类(class):
public class BazView extends BaseView {
// name, description, other common attributes;
}
public class BazTypeAView extends BazView {
// attributes specific to Type A Baz;
}
public class BazTypeBView extends BazView {
// attributes specific to Type B Baz;
}
在我们的服务层中,我们有实现 BaseService 的服务方法:a BarService
,一个BazService
,一个BazTypeAService
,一个BazTypeBService
以及其他具有类似命名方案的方法,它们都具有返回它们负责的类或 List<class they are responsible for>
的方法。 。依次,这些方法中的每一个都会调用来自 BaseService 且签名为 GetObjects(Class Viewtype, Class BeanType, Criteria)
的方法。 ,其标准基于传递到特定方法方法中的参数。 Bean 位于服务层和数据访问层之间,与此并不真正相关。
该方案的示例:
public interface BaseService {
public BaseView getObject(Class viewType, class beanType, Integer id);
public List<BaseView> getObjects(Class viewType, class beanType, Criteria criteria);
}
public class BaseServiceImpl implements BaseService {
protected BaseView getObject(Class viewType, class beanType, Integer id){
BaseBean bean = (BaseBean) DataService.getobject (beanType, id);
BaseView view = ViewGenerator.createEmptyView(viewType);
copyAttributes(bean, view);
return view;
}
protected List<BaseView> getObject(Class viewType, class beanType, Criteria criteria){
List<BaseBean> bean = (List<BaseBean>) DataService.getobject (beanType, Criteria);
List<BaseView> view = new ArrayList<BaseView>();
copyAttributes(bean, view);
return view;
}
}
public interface BarService extends BaseService {
public BarView getBar(Integer id);
public List<BarView> getBars(BarView barView);
}
public class BarServiceImpl extends BaseServiceImpl implements BarService {
public BarView getBar(Integer id){
BarView bar = getObject(BarView.class, BarBean.class, id);
return bar;
}
public List<BarView> getBars(BarView barView){
Criteria criteria = getCriteriaFromBarView(barView);
List<BarView> bars = getObjects(BarView.class, BarBean.class, criteria);
return bars;
}
}
以上就是系统的大致工作原理。创建 Bar、获取 Bar 列表、更新 Bar 和删除 Bar 的方法实际上与上面相同。
问题在于 getObject 返回原始列表,导致大量 Eclipse 警告和难以阅读的代码。我们对该项目的警告中有超过 2/3 是关于原始类型的使用,尽管我们的代码仍然可以编译并按其应有的方式工作,但它有很多消息。
如果我们没有第二种扩展扩展类的 View,我们可以这样做 List<? extends Fooview>
,但这会给扩展 BazView 的类带来错误。当你同时拥有这两种类型时,有没有办法让泛型类型在这里工作?扩展基本 View 和?扩展 X 扩展 Baseview?
最佳答案
我的答案与其他人没有太大区别,只是我猜你的 BaseService 是一个接口(interface):
In our service layer, we have service methods implementing a BaseService
我会像这样定义界面(编辑):
public interface BaseService<T extends FooView>{
T getObject(Class<T> viewType, Class<? extends FooBean> beanType, Integer id);
List<T> getAllObjects(Class<T> viewType, Class<? extends FooBean> beanType);
}
(添加) 在抽象类中实现该接口(interface)要求所有依赖服务也使用泛型:
public abstract class BaseServiceImpl<T extends FooView> implements BaseService<T>{
@Override
public T getObject(Class<T> viewType, Class<? extends FooBean> beanType, Integer id){
FooBean bean = DataService.getObject(beanType, id);
T view = ViewGenerator.createEmptyView(viewType);
copyAttributes(bean, view);
return view;
}
@Override
public List<T> getAllObjects(Class<T> viewType, Class<? extends FooBean> beanType){
List<? extends FooBean> beanList = DataService.getAllObjects(beanType);
return beanList.stream().map(bean -> {
T view = ViewGenerator.createEmptyView(viewType);
copyAttributes(bean, view);
return view;
}).collect(Collectors.toList());
}
private void copyAttributes(FooBean bean, T view){}
}
(编辑) 那么所有服务的实现应该是直接的:
public class BarServiceImpl extends BaseServiceImpl<BarView> implements BarService{
@Override
public BarView getBar(Integer id){
return getObject(BarView.class, BarBean.class, id);
}
@Override
public List<BarView> getAllBars(){
return getAllObjects(BarView.class, BarBean.class);
}
}
public class BazServiceImpl extends BaseServiceImpl<BazView> implements BazService{
@Override
public BazView getBaz(Integer id){
return getObject(BazView.class, BazBean.class, id);
}
@Override
public List<BazView> getAllBazs(){
return getAllObjects(BazView.class, BazBean.class);
}
}
public class BazTypeAServiceImpl extends BaseServiceImpl<BazTypeAView> implements BazTypeAService{
@Override
public BazTypeAView getBazTypeA(Integer id){
return getObject(BazTypeAView.class, BazTypeABean.class, id);
}
@Override
public List<BazTypeAView> getAllBazTypeAs(){
return getAllObjects(BazTypeAView.class, BazTypeABean.class);
}
}
至少在我的主要方法中没有警告,因为所有内容都清晰地键入:
public class Main{
public static void main(String[] args){
BarService barService = new BarServiceImpl();
BarView barView = barService.getBar(111);
List<BarView> barViewList = barService.getAllBars();
BazService bazService = new BazServiceImpl();
BazView bazView = bazService.getBaz(222);
List<BazView> bazViewList = bazService.getAllBazs();
BazTypeAService bazTypeAService = new BazTypeAServiceImpl();
BazTypeAView bazTypeAView = bazTypeAService.getBazTypeA(333);
List<BazTypeAView> bazTypeAViewList bazTypeAService.getAllBazTypeAs();
}
}
注意:
用抽象类替换接口(interface)(如果可能)将再次减少代码,因为两个示例方法都可以在抽象类中实现。 main 方法根本不需要改变。
编辑
您还需要在创建对象的级别使用泛型。否则你需要大量的选角,并且你的列表中会出现那些丑陋的警告。我为您更新了示例。
编辑2
我之前已经提到过,您的 DataService 和 ViewGenerator 也需要使用泛型。这就是我实现方法体的方式:
public class DataService {
public static <T extends FooBean> T getObject(Class<T> beanType, Integer id){return null;}
public static <T extends FooBean> List<T> getAllObjects(Class<T> beanType){return null;}
}
public class ViewGenerator {
public static <T> T createEmptyView(Class<T> viewType){return null;}
}
关于java - 如何使扩展另一个扩展类的类与通用集合一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39143989/