Java 获取相似对象属性的广义方法
我有一个对象,它有几个数组作为字段。它的类大致如下所示:Java 获取相似对象属性的广义方法,java,generalization,Java,Generalization,我有一个对象,它有几个数组作为字段。它的类大致如下所示: public class Helper { InsuranceInvoices[] insuranceInvoices; InsuranceCollectiveInvoices[] insuranceCollectiveInvoices BankInvoices[] bankInvoices; BankCollectiveInvoices[] bankCollectiveInvoices; } 所有发票类
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循环中的代码重复让我感到不舒服。我必须对四个不同数组中的所有invoice对象执行完全相同的操作。因此,每个循环有四个循环,这是不必要的代码膨胀
有没有一种方法可以编写通用(私有)方法?一个想法是:
private void generalMethod(Invoice[] invoiceArray){
// ...
}
但是这需要四个检查实例,因为类Invoice不知道方法getCusomterId()。因此,我将一无所获;该方法仍将包含重复我感谢所有可能的解决方案来推广这个问题 它并不漂亮,但是您可以使用反射来查找
getCustomerId
,然后再查找它,cf
请注意这是未经测试的。如果不允许您通过添加自定义接口来更改正在处理的类。您可以做的最好的事情是使用具有所需属性的自定义类包装它们 通过这种方式,您将拥有一个包含所有“不太好”代码的类,这些代码将您无法接触的类转换为符合适当和有用设计的好类
例如,您可以拥有一个类
WrappedInsuranceInvoice
,该类扩展了WrappedInsurace
,并包含一个成员字段InsuranceInvoice
。如果您不需要保留原始类,那么通过复制数据可以更好地关闭该类。例如,通过这种方式,您可能会丢失数组而改用列表。概括问题的可能解决方案(从最佳到最差排序):
使用包装类
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
}
public class CustomerIdHelper {
public static String getID(Invoice invoice) {
if (invoice instanceof InsuranceInvoices) {
return ((InsuranceInvoices) invoices).getCustomerID();
} else if ...
}
}
Upd如果我理解正确,您需要对所有数组中的ID执行一些操作。要使用InvoiceWrapper,还需要在Helper类中实现迭代器,它将遍历数组并为每个条目返回一个包装器。因此,您的代码无论如何都可以使用4个数组
使用强制转换实例
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
}
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);
}
}
因此,这些类都实现了
Invoice
,并且都实现了getCustomerId
,但是getCustomerId
不在Invoice
界面中?您必须使用反射按名称访问该方法并调用它。在这一点上,发票
界面是非常无用的。是否获取保险发票
,获取银行发票
…所有四个都返回相同数量的发票?我有一个建议。。。将cluebat应用于将发票
接口作为标记接口的人,而不是指定发票有哪些共同方法的人。我没有足够的资源提供完整的答案,但听起来你在寻找duck类型:wiki显示使用dynamic,并且有c#duck类型解决方案,但这可能不值得这么做effort@njzk2这是正确的。反思也许是一种方式,但它通常被认为是一种“肮脏”,不是吗?谢谢你的建议!第一种方法是我没有考虑的。但是你能解释一下为什么你选择反射方法是三种方法中最差的一种吗?@DeMo这是因为如果有人删除了这个方法,你不会注意到它。在前两个变体中,您将看到编译错误。