java - 如何使扩展另一个扩展类的类与通用集合一起使用?

标签 java generics inheritance

在我们当前的代码库中,我们具有以下数据结构来在服务层和前端层之间进行通信:

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

我之前已经提到过,您的 DataServiceViewGenerator 也需要使用泛型。这就是我实现方法体的方式:

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/

相关文章:

ios - Swift func with generic where constraint is a protocol which self conforms

typescript - 在扩展类中覆盖具有不同参数类型的方法 - Typescript

java - Java实现二叉搜索树插入操作

java - Xstream 忽略已注册的转换器

java - 图片库教程已弃用

Java使用运行时获取的类型参数创建泛型实例

java - 为 LSH Minhash 算法生成随机哈希函数

java 模板形式参数与 Void

scala - 当类层次结构中有原始类型时,为什么 Scala 会提示非法继承?

javascript - 如何在类声明上实现伪经典继承?