A generalized method for obtaining similar object attributes

I have an object that has multiple arrays as fields. The class looks something like this:

public class Helper { InsuranceInvoices[] insuranceInvoices; InsuranceCollectiveInvoices[] insuranceCollectiveInvoices BankInvoices[] bankInvoices; BankCollectiveInvoices[] bankCollectiveInvoices; } 

All types of accounts have an interface of the mutual interface Invoice.
I need all invoices to call a different method on them.

 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 

The problem is that all invoices have a common token interface. The getCustomerID () method is not defined by an interface or class. This is a behavior that I cannot change due to this specification.

Repeating code inside a for-each-loop causes an error. I have to do the same on all count objects in four different arrays. Therefore, four for each loop that do not require bloating code.

Is there a way I can write a general (private) method? One idea:

 private void generalMethod(Invoice[] invoiceArray){ // ... } 

But this will require four instance checks because the Invoice class does not know the getCusomterId () method. Therefore, I wonโ€™t gain anything; the method will still contain repetitions.

I am grateful for all possible solutions to summarize this problem!

+7
java
source share
3 answers

Possible solutions to summarize the problem (ordered from best to worst):

Using a wrapper class

 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 } 

Update . If I understand correctly, you need to do something with identifiers in all arrays. To use InvoiceWrapper, you also need to implement an iterator in the Helper class, which will go through arrays and return a wrapper for each record. Thus, in any case, you will have code that works with 4 arrays.

Using cast instance

 public class CustomerIdHelper { public static String getID(Invoice invoice) { if (invoice instanceof InsuranceInvoices) { return ((InsuranceInvoices) invoices).getCustomerID(); } else if ... } } 

Calling methods by name via Reflection

 public class CustomerIdHelper { public static String getID(Invoice invoice) { Method method = invoice.getClass().getDeclaredMethod("getCustomerId"); return (String) method.invoke(invoice); } } 
+7
source share

This is not very, but you can use reflection to look at the getCustomerId Method , and then invoke () it, cf. Class.getDeclaredMethod () .

 private void generalMethod(Invoice[] invoiceArray){ try { for (Invoice invoice : invoiceArray) { Method getCustomerId = invoice.getClass().getDeclaredMethod("getCustomerId"); getCustomerId.invoke(invoice); } } catch (Exception e) { // ... } } 

Please note that this is not verified.

+2
source share

If you are not allowed to modify the classes you are processing, adding a custom interface to them. The best you can do is wrap them in a special class that has the desired properties.

Thus, you will have one class with all the "not very nice" code that converts classes that you cannot touch good classes that correspond to a correct and useful design.

For example, you might have a WrappedInsuranceInvoice class that extends WrappedInsurace and contains an InsuranceInvoice member field. If you do not need to keep the original class, you would be even better by copying the data. Thus, you can, for example, lose arrays and use lists.

+2
source share

All Articles