I have an object which has a few arrays as fields. It's class roughly looks like this:
public class Helper {
InsuranceInvoices[] insuranceInvoices;
InsuranceCollectiveInvoices[] insuranceCollectiveInvoices
BankInvoices[] bankInvoices;
BankCollectiveInvoices[] bankCollectiveInvoices;
}
All of the invoice types have a mutual marker interface Invoices.
I need to get all of the invoices to invoke another 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 only have the marker interface in common. The method getCustomerID() is not defined by a mutual interface or class. This is a behaviour I cannot change due to a given specification.
The code repetition inside the for-each-loop is something that bugs me. I have to do the exact same thing on all invoice objects in the four different arrays. Hence four for-each-loops that unecessary bloat the code.
Is there a way that I can write a general (private) method? One idea was:
private void generalMethod(Invoice[] invoiceArray){
// ...
}
But this would require four instanceof checks because the class Invoice doesn't know the method getCusomterId(). Therefore I would gain nothing; the method would still contain repetitions.
I'm thankful for every possible solution to generalize this problem!
Variables that belong to an object are usually called attributes, but you might also see them called “fields”. To access an attribute of an object, Java uses dot notation. For example: int x = blank.
Attributes. An object characteristic that is always present and occupies storage, even if the attribute does not have a value. In this respect, an attribute is similar to a field in a fixed-length data structure.
Yes, Python functions are objects. And because they're objects, they have attributes. And because they're objects, we can assign new attributes to them, as well as retrieve the values of those attributes.
Possible solutions to generalize the problem (ordered from best to worst):
Using 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
}
Upd If I understood correctly, you need to do something with IDs in all arrays. To use InvoiceWrapper, you also need to implement iterator in Helper class, that will walk through arrays and return a wrapper for each entry. So, you will have code that works with 4 arrays anyway.
Using instance of casts
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);
}
}
It's not pretty, but you could use reflection to look up 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) {
// ...
}
}
Do note that this is untested.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With