Я столкнулся с некоторым кодом сегодня, что я нашел сомнительным. Вот упрощенный пример (не реалистичен).
public interface IListable {
//returns first n items from list
public ArrayList getFirstNThings(int n);
//returns last n items from list
public ArrayList getLastNThings(int n);
}
Затем существует конструктор как так:
public GroceryList implements IListable {
private ArrayList<GroceryItem> groceries;
public GroceryList() {
this.groceries = new ArrayList<GroceryItem>();
}
public ArrayList<GroceryItem> getFirstNThings(int n) {
ArrayList<GroceryItem> firstNThings = new ArrayList<GroceryItem>();
for (int i=0; i < n; i++) {
firstNThings.add(this.groceries.get(i));
}
return firstNThings
}
public ArrayList<GroceryItem> getLastNThings(int n) {
ArrayList<GroceryItem> lastNThings = new ArrayList<GroceryItem>();
for (int i=this.groceries.size(); i < this.groceries.size()-n; i--) {
lastNThings.add(this.groceries.get(i-1);
}
return lastNThings;
}
}
Проигнорируйте любые проблемы реализации, которые можно найти в том (я нашел некоторых также). То, что я достигаю, - то, что интерфейс не использует универсального параметра типа для ArrayList (т.е. ArrayList<?>), но конструктор метода интерфейса делает (т.е. ArrayList <GroceryList>). Другие конструкторы могут возвратить ArrayLists с какими-либо другими параметрами типа, нет?
Так мои вопросы: действительно ли это - проблема? Я должен осуществить рефакторинг что-нибудь? Действительно ли это стоит того? Каково преимущество? С какими проблемами я могу столкнуться, если мне определили метод в интерфейсе, тип возврата которого является необработанным типом, но фактические конструкторы метода возвращают различные параметризованные типы?
если оба метода IListable всегда возвращают один и тот же тип, используйте это вместо:
public interface IListable<T> {
//returns first n items from list
public ArrayList<T> getFirstNThings(int n);
//returns last n items from list
public ArrayList<T> getLastNThings(int n);
}
если это не вариант, попробуйте использовать ? вместо этого. Хотя это в принципе то же самое, это позволяет избежать некрасивых предупреждений.
public interface IListable {
//returns first n items from list
public ArrayList<?> getFirstNThings(int n);
//returns last n items from list
public ArrayList<?> getLastNThings(int n);
}
Как правило, использование более специфического возвращаемого типа в реализации не является проблемой, чем в супертипе или интерфейсе. Если вы имеете дело с IListable, вам нужно обрабатывать любой тип объекта в возвращаемом списке. Если вы имеете дело с GroceryList, вы ожидаете только GroceryItems. Это справедливо не только для аргументов генетических типов возвращаемых типов, но и для самого возвращаемого типа. Так что если интерфейс определяет List
, можно реализовать его как ArrayList
.