Подтвердить что ты не робот

Лучше ли использовать List или Collection?

У меня есть объект, который хранит некоторые данные в списке. Реализация может измениться позже, и я не хочу раскрывать внутреннюю реализацию конечному пользователю. Однако пользователь должен иметь возможность изменять и получать доступ к этому набору данных. В настоящее время у меня есть что-то вроде этого:

public List<SomeDataType> getData() {
   return this.data;
}

public void setData(List<SomeDataType> data) {
   this.data = data;
}

Означает ли это, что я позволил пропустить внутренние детали внедрения? Должен ли я делать это вместо этого?

public Collection<SomeDataType> getData() {
   return this.data;
}

public void setData(Collection<SomeDataType> data) {
   this.data = new ArrayList<SomeDataType>(data);
}
4b9b3361

Ответ 1

Это зависит от того, хотите ли вы, чтобы ваши пользователи могли индексировать данные? Если да, используйте Список. Оба являются интерфейсами, поэтому вы не испытываете утечки деталей реализации, на самом деле вам просто нужно решить минимальную функциональность.

Ответ 2

Возврат списка соответствует программированию на максимально подходящий интерфейс.

Возвращение коллекции вызовет неопределенность для пользователя, поскольку возвращенная коллекция может быть либо: Set, List или Queue.

Ответ 3

Независимо от возможности индексирования в список через List.get(int), у пользователей (или у вас) есть ожидание того, что элементы коллекции находятся в надежном и предсказуемом порядке? Может ли коллекция иметь кратность одного и того же элемента? Оба они - ожидания списков, которые не являются общими для более общих коллекций. Это те тесты, которые я использую при определении того, какая абстракция будет показана конечному пользователю.

Ответ 4

При возврате реализации интерфейса или класса, который находится в высокой иерархии, эмпирическое правило состоит в том, что объявленный тип возвращаемого значения должен быть ВЫСОКИМ уровнем, который обеспечивает минимальную функциональность, которую вы готовы гарантировать для вызывающего, и что вызывающий абонент разумно нуждается. Например, предположим, что вы действительно вернулись, это ArrayList. ArrayList реализует список и коллекцию (среди прочего). Если вы ожидаете, что вызывающий абонент должен будет использовать функцию get (int x), то это не сработает для возврата коллекции, вам нужно будет вернуть List или ArrayList. До тех пор, пока вы не видите причин, по которым вы когда-либо изменили бы свою реализацию, чтобы использовать что-то другое, кроме списка, например Set, тогда правильный ответ - вернуть список. Я не уверен, есть ли какая-либо функция в ArrayList, которая отсутствует в списке, но если есть, будут применяться те же рассуждения. С другой стороны, как только вы вернете Список вместо коллекции, вы в какой-то мере заблокировали свою реализацию. Чем меньше вы вкладываете в свой API, тем меньше ограничений вы вносите в будущие улучшения.

(На практике я почти всегда возвращаю List в таких ситуациях, и он никогда меня не сгорел, но я, вероятно, действительно должен вернуть коллекцию.)

Ответ 5

Использование наиболее общего типа, которое представляет собой Collection, имеет наибольший смысл, если только не существует явной причины использовать более конкретный тип - List. Но что бы вы ни делали, если это API для общественного потребления, в документации должно быть ясно, что он делает; если он возвращает мелкую копию коллекции, скажите это.

Ответ 6

Да, ваша первая альтернатива делает детали реализации утечки, если она не является частью вашего интерфейса, что метод всегда будет возвращать список. Кроме того, использование кода пользователя для замены экземпляра вашей коллекции несколько опасно, потому что реализация, в которой они проходят, может вести себя не так, как вы ожидаете.

Конечно, все зависит от того, насколько вы доверяете своим пользователям. Если вы возьмете философию Python, что "мы все согласны с взрослыми здесь", то первый метод просто прекрасен. Если вы считаете, что ваша библиотека будет использоваться неопытными разработчиками, и вам нужно сделать все возможное, чтобы "присматривать" за ними и убедиться, что они не делают что-то не так, предпочтительнее не позволять им устанавливать коллекцию, а не возвращать фактический сбор. Вместо этого верните (неглубокую) копию.

Ответ 7

Если бы я занимался скрытием внутреннего представления моих данных внешнему пользователю, я бы использовал либо XML, либо JSON. В любом случае, они довольно универсальны.

Ответ 8

Это зависит от того, какие гарантии вы хотите предоставить пользователю. Если данные являются последовательными, так что порядок элементов имеет значение, и вы разрешаете дубликаты, используйте список. Если порядок элементов не имеет значения, и дубликаты могут или не могут быть разрешены, используйте коллекцию. Поскольку вы фактически возвращаете базовую коллекцию, вы не должны иметь и функцию get и set, а только функцию get, так как возвращаемая коллекция может быть мутирована. Кроме того, предоставление функции set позволяет изменять тип коллекции пользователем, тогда как вы, вероятно, хотите, чтобы определенный тип контролировался вами.