java - Java, Inheritance, Generics - using parameters of subtypes in template method implementations
问题描述
I am building an application that is generating PDF documents for sales orders and sales invoices. For simplicity I have exluded redundant logic and fields.
Here is my class structure:
public class SalesEntity {
public String name;
public String createdDate;
}
public class SalesOrder extends SalesEntity {
}
public class SalesInvoice extends SalesEntity {
public String invoiceSpecificField;
}
and similar scturcure for wrapper and list items:
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;
}
and here is first part of the problem.
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;
}
For building mechanism I am using template method:
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 */
}
}
}
And if first part of somwhow solveable, here comes main part:
Question: How can I make specific template method implementations (OrderPDFBuilder, InvoicePDFBuilder
)
receive parameters of subtype SalesEntityResponse
(SalesOrderResponse
and SalesInvoiceResponse
) respectively? So that in specific implementations I can use specific fields of those entities. Does it make sense? I assume here is something related to bounded types, but I am not sure how to use it properly.
解决方案
As you've established generics are how you achieve this. So firstly you'll need to stick your generics decleration on the SalesEntityResponse
:
public class SalesEntityResponse<T extends SalesEntity, U extends SalesEntityItem> {
public T salesEntity;
public List<U> salesEntityItems;
}
Then in the declaration of your subtypes you tell it what concrete types they hold:
public class SalesOrderEntityResponse extends SalesEntityResponse<SalesOrder, SalesOrderItem> {
}
To make the "magic" work in your addItems
method you'll have to also have to add generics to which ever class/interface declares the addItems
method, this is presumably AbstractPDFBuilder
? So something like:
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;
}
}
And then your concrete PDFBuilder
types need to supply the relavant generics:
public class SalesOrderPDFBuilder extends AbstractPDFBuilder<SalesOrder, SalesOrderItem, SalesOrderEntityResponse> {
protected void addItems(Document document, SalesOrderEntityResponse entityResponse) {
}
}
推荐阅读
- javascript - 用圆圈观察标记中位置/半径的变化
- runtime - NET运行时消耗资源
- powershell - 如何通过 PowerShell 创建具有特定内容类型的 SharePoint 文档?
- python - 分层聚类(自下而上聚类)在较近的点之前合并较远的点(用于各种链接标准)
- python - 如何通过 python 代码本身将一行附加到 .py 文件?
- python - 如何让我的 Pygame Sprite 跳得更高更远?
- django - 向用户添加一个额外的字段(创建包含该字段的用户)
- asp.net - 如何设置 IIS 用户/权限以在 Web 应用程序中执行 Process.start()?
- php - 如何使(显示)仅购物车总数在底部固定(粘性)并且可单击以在移动视图上结帐#only?
- r - 使用 5 个类别在 r 中创建成对组