具有类型安全实现的Java通用接口 [英] Java generic interfaces with typesafe implementations

查看:151
本文介绍了具有类型安全实现的Java通用接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找从通用框架调用特定接口的好选择。我将以代码为例。查看问题部分,示例代码主要包括在内,以便将实例置于真实场景中。

I'm look for good alternatives to invoking a specific interface from a generic framework. I'll exemplify with code. Look to the question part, the example code is primarily included for thoroughness, and for putting the example into a real scenario.

假设我们要根据组件列表构建一个报表。假设我们有两个特定的组件类型:

Assume we want to build a report based on a list of components. Say we have two specific component types:

public interface Component { ... }
public class PDFComponents extends Component { ... }
public class WordComponents extends Component { ... }

每个组件都一个ReportBuilder实现,例如,

Each component has a ReportBuilder implementation, e.g.,

public interface ReportBuilder { ... }
public class PDFReportBuilder extends ReportBuilder { ... }
public class WordReportBuilder extends ReportBuilder { ... }

哪些构建特定的报告实现

Which builds specific report implementations

public interface Report { ... }
public class PDFReport extends ReportBuilder { ... }
public class WordReport extends ReportBuilder { ... }

最后我们有了定位组件的服务,报告出组件。

Finally we have the service which locates components and produces a report out of the components.

public class ReportService {
    ReportComponentRepository repo;
    List<ReportBuilder> builders;

    public <T extends Report> T getReport(Class<T> reportType) {
        // Get report components. E.g., this might return List<PDFComponent>
        List<Component> reportComponents = repo.getReportComponents(id);

        // Build report from components using one of the registered builders
        for (ReportBuilder builder : builders) {
            if (builder.buildFor(reportType) {
                return builder.buildReport(report);
            }
        }
    }
}

使用服务的示例

List<PDFReport> reports = new ReportService().getReport(PDFReport.class);



问题



问题。我如何设计一个通用的ReportBuilder界面,允许类似的安全性实现?

Question

Now to the question. How can I design a generic ReportBuilder interface which allows typesafety to it's implementations?

例如,选择界面:

public Report buildReport(List<? extends Component> components);

将导致其执行中的丑陋:

would cause ugliness in it's implementations:

public class PDFReportBuilder implements ReportBuilder {

    @Override
    public Report buildReport(List<? extends Component> components) {
         PDFReport report;

         for (Component component : components) {
            if (component instanceOf PDFComponent) {
                // assemble report ... 
                report.includeComponent(component);
            }
        }

        return report;
    }
}

当我们真正希望PDFReportBuilder的界面为例,

when we really desire the interface for PDFReportBuilder to be e.g.,

 public Report buildReport(List<PDFComponent> component) { ... }


推荐答案

如果您将Component的类型设置为ReportBuilder的类型变量,则可以工作:

It works if you make the type of Component into a type variable for ReportBuilder:

public interface ReportBuilder<T extends Component> {
    public Report buildReport(List<T> components);
}

public class PDFReportBuilder implements ReportBuilder<PDFComponent> {
    public Report buildReport(List<PDFComponent> components);
}

您必须评估您是否真的希望在ReportBuilder中使用类型变量。这并不总是正确的选择。另外,如果您还要 PDFReportBuilder.buildReport 具有PDFReport的返回类型,那么您需要将其作为类型变量(即 public interface ReportBuilder< T extends Component,S extends Report> )。

You'll have to evaluate whether you really want a type variable in ReportBuilder though. It's not always the correct choice. Additionally, if you also want PDFReportBuilder.buildReport to have a return type that is PDFReport, then you need to have that as a type variable as well (i.e., public interface ReportBuilder<T extends Component, S extends Report>).

这篇关于具有类型安全实现的Java通用接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆