Перегрузка функции Java с помощью параметра List <>
У меня есть 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)
...
но они рассматриваются как повторяющиеся методы... есть ли хороший способ сделать это, а не просто иметь две разные функции?
Ответы
Ответ 1
Если вы оба класса реализуете общий интерфейс,
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());
}
}
Ответ 2
Что касается дженериков в Java, так это то, что общие типы стираются во время выполнения, поэтому оба этих метода скомпилируются под одну и ту же подпись. Вам нужно будет иметь отдельные имена методов или проверить тип элементов списка во время выполнения.
Ответ 3
В генераторах есть так называемое стирание типа - List<Customer>
и List<Applicant>
- это один и тот же тип, компилятор просто устанавливает ограничения времени компиляции на то, что вы можете с ними делать.
Вы можете проверить тип первого объекта в списке и вызвать на нем внутренний (по-другому) внутренний метод.
Ответ 4
Один из способов решения этой проблемы - определить настраиваемые типы списков, например:
class CustomerList extends ArrayList<Customer> {
...
}
class ApplicantList extends ArrayList<Applicant> {
...
}
Тогда следующая перегрузка будет законной:
public void processCustomerNumbers(CustomerList custList)
public void processCustomerNumbers(ApplicantList appList)
Однако я не думаю, что это была бы хорошая идея. Для начала он прокладывает определенные классы реализации в API приложений.
Лучшим подходом является определение общего интерфейса для Клиента и Заявителя, который позволяет обрабатывать их одним методом processCustomerNumbers
. (Как подробно описано в других ответах.)
Ответ 5
Вместо этого используйте массив.
public void processCustomerNumbers(Customer[] custList)
...
public void processCustomerNumbers(Applicant[] appList)
...
Когда вы пытаетесь вызвать эти методы со списком, преобразуйте список в массив:
List<Customer> customers;
List<Applicant> applicants;
...
processCustomerNumbers(customers.toArray(new Customer[]{});
processCustomerNumbers(applicants.toArray(new Applicant[]{});
Ответ 6
Прежде чем приступать к именам методов, иерархия классов немного запутывает...
public class Customer{
...
public String getCustomerNumber();
...
}
public class Applicant{
....
private Customer c;
public Customer getCustomer(){ return c; }
...
}
Почему заявитель и клиент должны быть разные объекты? Можете ли вы рассказать связь между этими объектами?