获取类似对象属性的通用方法

时间:2015-06-18 13:17:14

标签: java generalization

我有一个对象,它有一些数组作为字段。它的课程大致如下:

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()。因此,我什么也得不到;该方法仍然包含重复。

我很感谢每一种可能的解决方案来概括这个问题!

3 个答案:

答案 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() 。如果您不需要保留原始课程,则通过复制数据可以更好。这样你就可以丢失数组并改用列表。