2013-06-19 1 views
1

Я отправлю свой вопрос внизу.Как создать правильный тип возврата?

Ниже приведен класс, из которого распространяются другие классы.

public class people { 

    class family extends people { 
    } 

    class friends extends people { 
    } 

    class coworkers extends people {  
    } 
} 

Ниже класс, который имеет метод getAllPeopleByClass, который получает вызывается getMembers() метод в классах выбора:

public class processing { 

static processing process = null; 
private Collection<family> familyList = new ArrayList<family>(); 
private Collection<coworkers> cowList = new ArrayList<coworkers>(); 
private Collection<friends> friendList = new ArrayList<friends>(); 

public processing(){ 
} 

public static processing getInstance() { 
    if (process == null) 
     process = new processing(); 
    return process; 
} 

public <T> Collection<people> getAllPeopleByClass(Class<T> clazz) { 
    Collection<people> peopleCollection; 
    peopleCollection.addAll(getList(clazz)); 
    return peopleCollection; 
} 

private <T> Collection<? extends people> getList(Class<T> clazz) { 
    if (clazz == family.class) { 
     return familyList; 
    } else if (clazz == coworkers.class) { 
     return cowList; 
    } else { // else if clazz == friends.class 
     return friendList; 
    } 
} 

И, наконец, классы, которые используют обработку:

public class familySelection { 
    public Collection<family> getMembers() { 
    Collection<family> f; 
    f = processing.getInstance().getAllPeopleByClass(family.class); //type mismatch 
    return f; 
    } 
} 

public class coworkerSelection { 
    public Collection<coworkers> getMembers() { 
    Collection<coworkers> c; 
    c = processing.getInstance().getAllPeopleByClass(coworkers.class); //type mismatch 
    return c; 
    } 
} 


public class friendsSelection { 
    public Collection<friends> getMembers() { 
    Collection<friends> f; 
    f = processing.getInstance().getAllPeopleByClass(friends.class); //type mismatch 
    return f; 
    } 
} 

Моя проблема в том, что я получаю несоответствие типов от вызова getAllPeopleByClass в каждом из моих методов getMembers().

Я попытался это:

public class familySelection { 
    public Collection<family> getMembers() { 
    Collection<? extends people> f; //changed to extend from people 
    f = processing.getInstance().getAllPeopleByClass(family.class); 
    return (Collection<family>) f; //cast warning - dont want that 
    } 
} 

Это работает, но я получаю предупреждение произнесения, что я не хочу, и я не хочу, чтобы подавить его. Это самое близкое, что я придумал для решения проблемы. Кроме того, возвращаемый тип getMembers() должен оставаться как есть. У кого-нибудь есть способ сделать это без каких-либо предупреждений? Или даже как-то справиться с этим в целом? Благодаря!

+0

Основная проблема в вашем дизайне является то, что генерик для компиляции исполнения типа времени, но вы выполняете проверку типа во время выполнения. Возможно, рассмотрим наличие 3 отдельных методов для возврата каждого типа коллекции. – nitegazer2003

ответ

2
public <T> Collection<T> getAllPeopleByClass(Class<T> clazz) { 
    Collection<T> peopleCollection = new ArrayList<T>(); 
    for(people p : getList(clazz)) { 
     peopleCollection.add(clazz.cast(p)); 
    } 
    return peopleCollection; 
} 
+0

Не работает.! – darijan

+0

Вы даже читали: Это работает, но я получаю предупреждение о броске, которого я не хочу, и я не хочу его подавлять. – darijan

+1

@ darijan - вы полностью читали мой (обновленный) ответ? «из-за ограничений java generics ...». это «самый правильный», какой может быть. – jtahlborn

1

Используйте super ключевое слово:

public class familySelection { 
    public Collection<? super family> getMembers() { 
    Collection<? super family> f; 
    f = processing.getInstance().getAllPeopleByClass(family.class); 
    return f; 
    } 
} 

UPD: Используйте super подстановочные, когда вы только put значения в структуру. Используйте шаблон extends, когда вы только get значения из структуры. И не используйте подстановочные знаки, когда используете как get, так и put.

+0

это скомпилируется, но это будет не очень полезно.наличие коллекции какого-либо типа, являющегося суперклассом семейства, не более полезно, чем просто не использовать дженерики вообще. – jtahlborn

+0

OP действительно сказал, что возвращаемый тип getMembers() должен оставаться как есть – nitegazer2003

0

Я бы выбрал эту версию. Это также требует подавления предупреждений, но я думаю, что это лучшее место для этого.

Я также позволил себе изменить вашу реализацию Singleton. Если вы действительно хотите это сделать, подумайте об использовании перечисления.

public enum processing { 
    INSTANCE; 

    private Collection<family> familyList = new ArrayList<family>(); 
    private Collection<coworkers> cowList = new ArrayList<coworkers>(); 
    private Collection<friends> friendList = new ArrayList<friends>(); 

    public static processing getInstance() { 
     return INSTANCE; 
    } 

    public <T extends people> Collection<T> getAllPeopleByClass(Class<T> clazz) { 
     Collection<T> peopleCollection = new ArrayList<T>(); 
     peopleCollection.addAll(getList(clazz)); 
     return peopleCollection; 
    } 

    @SuppressWarnings("unchecked") 
    private <T extends people> Collection<T> getList(Class<T> clazz) { 
     if (clazz == family.class) { 
      return (Collection<T>) familyList; 
     } else if (clazz == coworkers.class) { 
      return (Collection<T>) cowList; 
     } else { // else if clazz == friends.class 
      return (Collection<T>) friendList; 
     } 
    } 
} 

И familySelection:

public class familySelection { 
    public Collection<family> getMembers() { 
     Collection<family> f = processing.getInstance().getAllPeopleByClass(family.class); 
     return f; 
    } 
} 
+0

Спасибо за сообщение. Почему вы предпочитаете иметь предупреждения, когда их можно устранить все вместе? –

+0

Я начал писать свой ответ, прежде чем @jtahlborn отредактировал его версию. –

+0

И еще одно: возможно, в большинстве случаев это не важно, но он должен выполнить метод cast (p) для каждого объекта в коллекции. И он может это сделать, не рискуя ClassCastException только потому, что знает реализацию метода getList (clazz). Поэтому он также делает непроверенный бросок, это просто не так очевидно - и вам не нужно его подавлять. –