【问题标题】:Java, Inheritance, Generics - using parameters of subtypes in template method implementationsJava,继承,泛型 - 在模板方法实现中使用子类型的参数
【发布时间】:2020-04-09 01:14:34
【问题描述】:

我正在构建一个为销售订单和销售发票生成 PDF 文档的应用程序。为简单起见,我排除了冗余逻辑和字段。

这是我的班级结构:

public class SalesEntity {
    public String name;
    public String createdDate;
}

public class SalesOrder extends SalesEntity {
}

public class SalesInvoice extends SalesEntity {
    public String invoiceSpecificField;
}

以及用于包装器和列表项的类似结构:

public class SalesEntityItem {
    public String name;
    public String price;
}

public class SalesOrderItem extends SalesEntityItem {
}

public class SalesInvoiceItem extends SalesEntityItem {
    public String invoiceItemSpecificField;
}

public class SalesEntityResponse {
    public SalesEntity salesEntity;
    public List<SalesEntityItem> salesEntityItems;
}

这是问题的第一部分。

public class SalesOrderEntityResponse extends SalesEntityResponse {
//    public SalesOrder salesEntity; <-- say somehow to java that in this subclass the property type should also be subclass
//    public List<SalesOrderItem> salesEntityItems;
}

对于构建机制,我使用的是模板方法:

public class PDFBuilder extends AbstractPDFBuilder {
    protected void buildPdfDocument(Map<String, Object> model /*...*/) throws Exception {
        /*...*/
        addEntityNumber(document, salesEntityResponse);
        addItems(document, salesEntityResponse);
    }
}

public class OrderPDFBuilder extends PDFBuilder {
    /*...*/
    @Override
    protected void addEntityNumber(Document document, SalesEntityResponse entityResponse) throws DocumentException {
        /*...*/
        PdfPTable documentNameTable = new PdfPTable(1);
        Phrase documentNamePhrase = new Phrase(entityResponse.labels.account_number, timesFont);
        PdfPCell documentNameCell = new PdfPCell(documentNamePhrase);
        documentNameTable.addCell(documentNameCell);
        document.add(documentNameTable);
    }

    @Override
    protected void addItems(Document document, SalesEntityResponse entityResponse) throws DocumentException {
        /*...*/
        for (SalesEntityItem salesEntityItem : entityResponse.salesEntityItems) {
            /* Items adding specific logic */
        }
    }
}

如果 somwhow 的第一部分可以解决,那么主要部分如下: 问题:如何进行具体的模板方法实现(OrderPDFBuilder, InvoicePDFBuilder) 分别接收子类型SalesEntityResponseSalesOrderResponseSalesInvoiceResponse)的参数?因此,在特定的实现中,我可以使用这些实体的特定字段。是否有意义?我假设这里是一些与有界类型有关的东西,但我不确定如何正确使用它。

【问题讨论】:

标签: java generics inheritance types


【解决方案1】:

既然您已经建立了泛型,那么您就是如何实现这一点的。所以首先你需要把你的泛型声明放在SalesEntityResponse

public class SalesEntityResponse<T extends SalesEntity, U extends SalesEntityItem> {
    public T salesEntity;
    public List<U> salesEntityItems;
}

然后在子类型的声明中告诉它它们拥有哪些具体类型:

public class SalesOrderEntityResponse extends SalesEntityResponse<SalesOrder, SalesOrderItem> {

}

要使“魔法”在您的 addItems 方法中发挥作用,您还必须添加泛型,以使任何类/接口声明 addItems 方法,这大概是 AbstractPDFBuilder?所以像:

public abstract class AbstractPDFBuilder<T extends SalesEntity, U extends SalesEntityItem, V extends SalesEntityResponse<T, U>> {
    protected abstract void addItems(Document document, V entityResponse) throws DocumentException;
    }
}

然后你的具体PDFBuilder 类型需要提供相关的泛型:

public class SalesOrderPDFBuilder extends AbstractPDFBuilder<SalesOrder, SalesOrderItem, SalesOrderEntityResponse> {
    protected void addItems(Document document, SalesOrderEntityResponse entityResponse) {
    }
}

【讨论】:

  • 这正是我正在寻找的,我只是无法用语法正确地理解它:)
猜你喜欢
  • 1970-01-01
  • 2020-03-02
  • 1970-01-01
  • 1970-01-01
  • 2021-10-11
  • 2018-10-24
  • 1970-01-01
  • 2022-01-09
  • 1970-01-01
相关资源
最近更新 更多