我有一个对象,它有一些数组作为字段。它的课程大致如下:
public class Helper {
InsuranceInvoices[] insuranceInvoices;
InsuranceCollectiveInvoices[] insuranceCollectiveInvoices
BankInvoices[] bankInvoices;
BankCollectiveInvoices[] bankCollectiveInvoices;
}
所有发票类型都有一个共同标记界面发票。
我需要获取所有发票才能调用其他方法。
Helper helperObject = new Helper();
// ...
for (InsuranceInvoices invoice : helperObject.getInsuranceInvoices()) {
Integer customerId = invoice.getCustomerId();
// ...
}
for (BankInvoices invoice : helperObject.getBankInvoices()) {
Integer customerId = invoice.getCustomerId();
// ...
}
// repeat with all array fields
问题是所有发票只有标记接口。方法 getCustomerID()不是由相互接口或类定义的。这是一种由于给定的规范而无法改变的行为。
for-each-loops中的代码重复是让我烦恼的事情。我必须对四个不同阵列中的所有发票对象执行完全相同的操作。因此,四个for-each-loops不必要地膨胀代码。
有没有办法可以编写一般(私有)方法?一个想法是:
private void generalMethod(Invoice[] invoiceArray){
// ...
}
但是这需要四次实例检查,因为 Invoice 类并不知道方法 getCusomterId()。因此,我什么也得不到;该方法仍然包含重复。
我很感谢每一种可能的解决方案来概括这个问题!
答案 0 :(得分:7)
概括问题的可能解决方案(从最佳到最差排序):
使用包装类
public class InvoiceWrapper {
private String customerID;
public String getCustomerID() {
return customerID;
}
public InvoiceWrapper(BankInvoices invoice) {
this.customerID = invoice.getCustomerID();
}
public InvoiceWrapper(InsuranceInvoices invoice) {
this.customerID = invoice.getCustomerID();
}
// other constructors
}
更新 如果我理解正确,您需要对所有数组中的ID执行某些操作。要使用InvoiceWrapper,还需要在Helper类中实现迭代器,它将遍历数组并为每个条目返回一个包装器。因此,无论如何,您将拥有适用于4个阵列的代码。
使用强制转型实例
public class CustomerIdHelper {
public static String getID(Invoice invoice) {
if (invoice instanceof InsuranceInvoices) {
return ((InsuranceInvoices) invoices).getCustomerID();
} else if ...
}
}
通过反思按名称调用方法
public class CustomerIdHelper {
public static String getID(Invoice invoice) {
Method method = invoice.getClass().getDeclaredMethod("getCustomerId");
return (String) method.invoke(invoice);
}
}
答案 1 :(得分:2)
它不漂亮,但你可以使用反射来查找getCustomerId
Method然后invoke()它,参见Class.getDeclaredMethod()
private void generalMethod(Invoice[] invoiceArray){
try {
for (Invoice invoice : invoiceArray) {
Method getCustomerId = invoice.getClass().getDeclaredMethod("getCustomerId");
getCustomerId.invoke(invoice);
}
} catch (Exception e) {
// ...
}
}
请注意这是未经测试的。
答案 2 :(得分:2)
如果您不允许通过向其添加自定义界面来更改您正在处理的类。您可以做的最好的事情是使用具有所需属性的自定义类来包装它们。
通过这种方式,你将拥有一个课程,所有人都不会那么好。将您无法触及的类转换为匹配正确且有用的设计的优秀类的代码。
例如,您可以使用WrappedInsuranceInvoice
扩展WrappedInsurace
并包含成员字段InsuranceInvoice
的类ggplot(kbsdiv13CTN, aes(x=date, y=rev(depth), fill=mean)) +
geom_tile() + scale_fill_gradient(low = "white", high = "black") +
scale_y_reverse()
。如果您不需要保留原始课程,则通过复制数据可以更好。这样你就可以丢失数组并改用列表。