2010-02-11 14 views
10

mam 2 klasfunkcja Przeciążenie Java z List <> parametru

public class Customer{ 
    ... 
    public String getCustomerNumber(); 
    ... 
} 

public class Applicant{ 
    .... 
    private Customer c; 
    public Customer getCustomer(){ return c; } 
    ... 
} 

Kiedy prezentowane z listy klientów lub wnioskodawców chcę funkcję, która wykonuje iteracje listę i robi coś z CUSTOMERNUMBER.

Próbowałem przeciążania funkcji

public void processCustomerNumbers(List<Customer> custList) 
... 

public void processCustomerNumbers(List<Applicant> appList) 
... 

ale są one postrzegane jako duplikatów metod ... czy jest to dobry sposób na osiągnięcie tego raczej niż tylko o 2 różnie nazwane funkcje?

Odpowiedz

14

Jeśli się obie klasy wdrożyć wspólny interfejs,

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(); } 
    ... 
} 

następnie może być w stanie robić to, co chcesz, tylko z jednej metody:

public void processCustomerNumbers(List<? extends CustomerNumber> appList) { 
    for (Customer c: appList) { 
     processCustomerNumber(c.getCustomerNumber()); 
    } 
} 
+0

Dobra sugestia. –

12

Rzeczą o generykach w Javie jest to, że typy ogólne są usuwane w środowisku wykonawczym, więc obie te metody kompilują się do tego samego podpisu. Będziesz musiał mieć oddzielne nazwy metod lub sprawdzić typ elementów listy w czasie wykonywania.

+2

Java nie zawsze mają rodzajowych; kiedy zostały dodane, wynikowy kod nie został zmieniony. – Dolph

+3

Tak, to jest powód używania funkcji wymazywania typów - aby uniknąć łamania wstecznej zgodności z kodem pre-generics. – danben

+0

Typ jest usuwany w czasie wykonywania. Wybór przeciążenia metody odbywa się w czasie kompilacji. W związku z tym istnieje wystarczająca ilość informacji, aby mógł zdecydować kompilator, nawet po usunięciu. Istnieją jednak problemy z reprezentacją binarną i ze zgodnością, jeśli zmiana języka miała nastąpić. –

7

Leki generyczne mają, co jest znane jako typu skasowaniem - List<Customer> i List<Applicant> są tego samego typu, kompilator tylko kładzie kompilacji ograniczenia dotyczące tego, co można z nimi zrobić.

Można sprawdzić typ pierwszego obiektu na liście i wywołać na jego podstawie metodę wewnętrzną (inaczej nazwaną).

+0

Tak, to było coś, na co zacząłem patrzeć, sprawdzając klasę i zmieniając zachowanie. Przyszedłem do TAK, mając nadzieję, że pojawi się bardziej eleganckie rozwiązanie, jeśli nic nie wyjdzie, kontynuuję tę drogę. – MadMurf

+0

Jako inne pytanie, wybór nadpisuje się w czasie kompilacji, więc wymazanie nie wyklucza tego. –

-1

Przed przybyciem do nazwy metody , hierarchia klas jest trochę myląca ...

public class Customer{   
    ...   
    public String getCustomerNumber();   
    ...   
}   

public class Applicant{   
    ....   
    private Customer c;   
    public Customer getCustomer(){ return c; }   
    ...   
}  

Dlaczego wnioskodawca i Klient powinni być różnymi przedmiotami? Czy możesz powiedzieć, relacja między tymi obiektami ?

5

Jednym ze sposobów obejścia tego problemu byłoby określenie rodzajów list zwyczaj tak:

class CustomerList extends ArrayList<Customer> { 
    ... 
} 

class ApplicantList extends ArrayList<Applicant> { 
    ... 
} 

Potem następuje przeciążenie byłoby prawna:

public void processCustomerNumbers(CustomerList custList) 

public void processCustomerNumbers(ApplicantList appList) 

Jednakże, nie wiem pomyśl, że to byłby dobry pomysł. Na początek łączy różne klasy implementacji w interfejsy API twojej aplikacji.

Lepszym rozwiązaniem jest zdefiniowanie wspólnego interfejsu dla klienta i aplikanta, który umożliwia przetwarzanie go za pomocą jednej metody processCustomerNumbers. (Jak opisano w innych odpowiedziach).

0

Zamiast tego użyj tablicy.

public void processCustomerNumbers(Customer[] custList) 
... 

public void processCustomerNumbers(Applicant[] appList) 
... 

Podczas próby wywołania tych metod z listy, konwersji listy do tablicy:

List<Customer> customers; 
List<Applicant> applicants; 
... 
processCustomerNumbers(customers.toArray(new Customer[]{}); 
processCustomerNumbers(applicants.toArray(new Applicant[]{}); 
Powiązane problemy