У меня есть 2 класса
public class Customer{
...
public String getCustomerNumber();
...
}
public class Applicant{
....
private Customer c;
public Customer getCustomer(){ return c; }
...
}
При дарившем список клиентов или заявителей я хочу функцию, которая выполняет итерации списка и делает что-то с CustomerNumber.
Я попытался перегрузить функцию
public void processCustomerNumbers(List<Customer> custList)
...
public void processCustomerNumbers(List<Applicant> appList)
...
но они рассматриваются как повторяющиеся методы... там хороший способ сделать это вместо того, чтобы просто иметь 2 по-другому именованных функции?
Если вы заставите оба класса реализовать общий интерфейс,
interface CustomerNumber {
String getCustomerNumber();
}
public class Customer implements CustomerNumber {
...
public String getCustomerNumber();
...
}
public class Applicant implements CustomerNumber {
....
private Customer c;
public Customer getCustomer() { return c; }
public String getCustomerNumber() { return getCustomer().getCustomerNumber(); }
...
}
тогда вы сможете делать то, что хотите, всего одним методом:
public void processCustomerNumbers(List<? extends CustomerNumber> appList) {
for (Customer c: appList) {
processCustomerNumber(c.getCustomerNumber());
}
}
Фишка дженериков в Java в том, что общие типы стираются во время выполнения, поэтому оба этих метода компилируются в одну сигнатуру. Вам нужно будет иметь отдельные имена методов или проверять тип элементов списка во время выполнения.
Одним из способов решения этой проблемы является определение типов настраиваемых списков следующим образом:
class CustomerList extends ArrayList<Customer> {
...
}
class ApplicantList extends ArrayList<Applicant> {
...
}
Тогда следующая перегрузка будет допустимой:
public void processCustomerNumbers(CustomerList custList)
public void processCustomerNumbers(ApplicantList appList)
Однако, Не думаю, что это было бы хорошей идеей. Для начала он встраивает определенные классы реализации в API вашего приложения.
Лучшим подходом является определение общего интерфейса для Заказчика и Заявителя, который позволяет обрабатывать их с помощью одного метода processCustomerNumbers
. (Как подробно описано в других ответах.)
Прежде чем перейти к именам методов, иерархия классов немного сбивает с толку ...
public class Customer{
...
public String getCustomerNumber();
...
}
public class Applicant{
....
private Customer c;
public Customer getCustomer(){ return c; }
...
}
Почему заявитель и заказчик должны быть разными объектами? Можете ли вы определить связь между этими объектами?
Generics имеют то, что известно как стирание типов - List
и List
являются одним и тем же типом, компилятор просто накладывает компилятивные ограничения на то, что вы можете делать с ними.
Вы можете проверить тип первого объекта в списке и вызвать (с другим именем) внутренний метод, основанный на этом.