2013-05-24 4 views
2

У меня есть настройки структуры списка как такового:Последовательное наследование списков

List<List<Value>> l = new RowList(); 

, который дает ошибку "Type mismatch: Cannot convert from RowList to List<List<Value>>". Реализация осуществляется следующим образом:

public class RowList extends ArrayList<ValueList> 
public class ValueList extends ArrayList<Value> 

Значение - это объект в моей кодовой базе. Почему это не работает? Когда у меня есть это вместо того, все работает отлично:

public class RowList extends ArrayList<List<Value>> 

Для задания колледжа я работаю, код, что наш преподаватель написал произведение, вызывая метод, который возвращает List<List<Value>> внутри мой код, а затем добавить List<Value> к этот список. Поскольку программа предназначена для реализации базы данных, существует ряд требований, таких как ключевые значения, которые не встречаются более одного раза и т. Д. Чтобы проверить, что этого не происходит, мне нужно иметь класс ValueList или что-то подобное поэтому я могу расширить метод add(), чтобы проверить эти требования.

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

+1

Замечание по терминологии - «множественное наследование» обычно зарезервировано для случая, когда один класс наследуется от двух или более баз. В Java это поддерживается только в том случае, если все, кроме одного из «баз», являются интерфейсами, поэтому, как правило, считается, что Java не поддерживает множественное наследование, тогда как C++ делает (и Java специально решил не копировать это). Наличие цепей наследования обычно не называется «множественным наследованием», поэтому называть его «множественное наследование» немного запутанно. – Steve314

+0

@ Steve314 Я изменил его на «Последовательное наследование»: надеюсь, это менее двусмысленно. – user2282497

ответ

8

Плохая идея создать подклассы коллекций в первую очередь. Придерживайтесь стандартных реализаций и используйте композицию, а не наследование.

Теперь, чтобы понять, почему это не скомпилируется, вот почему, с кратким примером. Предположим, что вы хотите сделать, это возможно, и компилирует, вы могли бы сделать:

RowList rowList = new RowList(); 
List<List<Value>> listOfLists = rowList; 
listOfLists.add(new LinkedList<Value>()); 

И хотя RowList предполагается провести экземпляры только ValueList, вы бы тогда иметь LinkedList<Value> внутри, разрушая безопасность типов и правильность программы.

+0

Не могли бы вы рассказать о своем первом заявлении (не подклассы)? Со ссылкой, если это возможно? Благодарю. –

+1

См http://books.google.fr/books?id=ka2VUBqHiWkC&pg=PA81&lpg=PA81&dq=effective+java+composition&source=bl&ots=yYIoLmp4M_&sig=1rtWUGRN7uFUaIlWwGSYbndOeag&hl=fr&sa=X&ei=Lx-fUcn3CvGp7Abes4CQCQ&ved=0CD8Q6AEwAQ#v=onepage&q=effective% 20java% 20composition & f = false –

+0

@JBNizet Моя проблема в том, что для этого назначения требуется, чтобы возвращаемый список возвращался, чтобы другой класс мог добавлять/удалять элементы в/из. Мне нужно иметь возможность перехватывать эти добавления и удалять, чтобы проверить их достоверность. Если я использую композицию, то я не могу этого сделать. – user2282497

1

Проблема заключается в том, RowList не List<List<Value>>, так что List<List<Value>> l = new RowList(); не является действительным

Так же, как вы не можете сделать это:

List<Object> objList = new ArrayList<String>(); 

Есть несколько вариантов для вас:

Изменить декларация l как Список:

List<ValueList> l = new RowList(); 

или использования шаблона:

List<? extends List<Value>> l = new RowList(); 

Edit: Хотя это может быть решена с помощью выше подхода, ваша конструкция должна быть лучше рефакторинга. Я думаю, вы пытаетесь использовать наследование, чтобы сделать что-то вроде typedef в C/C++, но побочный эффект использования наследования для имитации typedef большой (по крайней мере, на Java), и вы должны подумать дважды, прежде чем делать это. Я не говорю, что вы не должны использовать наследование, если это действительно имеет смысл (т. Е. Вы действительно хотите, чтобы ValueList был - List<ValueList>). Однако мне кажется, что вы делаете это просто, чтобы сохранить ввод текста List<Value> вместо того, чтобы вводить осмысленный тип.

Смежные вопросы