Это плохая практика добавлять элементы в список с помощью метода getter в java?
Предположим, у меня есть private ArrayList
или LinkedList
внутри класса, что я никогда не назначу новую ссылку на него, или, другими словами, этого никогда не произойдет:
myLinkedList = anotherLinkedList;
так что мне не нужно будет использовать setMyLinkedList(anotherLinkedList)
.
но! Мне нужно добавить в него элементы или удалить из него элементы.
должен ли я написать новый вид
setter
только выполните заданиеadding
вместоsetting
, какmyLinkedList.add(someElement)
?-
или это OK для этого используйте
getter
, без неповиновениеEncapsulation
основные?getMyLinkedList().add(someElement)
( + предположим, я потеряю свою метку, если не подчинюсь инкапсуляции : -")
6 ответов
Я не думаю, что это особо большая практика, чтобы сделать что-то вроде:
myObj.getMyList().add(x);
поскольку вы подвергаете переменную частного класса не только для чтения, но, как говорится, я вижу ее довольно часто (я смотрю на вас, автоматически генерируемые классы). Я бы сказал, что вместо этого верните немодифицируемый список и разрешите пользователям класса добавлять в список с помощью явного метода:
public class MyClass{
private final List<String> myList = new ArrayList<String>();
public List<String> getList(){
return Collections.unmodifiableList(this.myList);
}
public void addToList(final String s){
this.myList.add(s);
}
}
редактировать после рассмотрения вашего комментарии, я хотел добавить немного о вашей идее сеттера:
Я имел в виду использование этой строки кода внутри нового типа сеттера внутри самого класса, например public void setter(someElement){this.myLinkedList.add (someElement);}
Если я правильно вас понимаю, вы говорите, что хотите выставить метод, который только добавляет к вашему списку. В целом это то, что я думаю, вы должны снимать, и то, что многие изложили в ответах, однако, маркировка это как сеттер немного вводит в заблуждение, так как вы ничего не переназначаете (устанавливаете). Это, и я настоятельно рекомендую вернуть список только для чтения из вашего метода геттера, если это возможно.
В общем случае вы не должны предполагать, что список, возвращаемый геттером, является оригинальным. Например, его можно украсить или проксировать. Если вы хотите предотвратить установку нового списка для целевого объекта, вместо этого можно определить метод add для целевого класса.
Я бы предложил в этом случае лучше всего следовать вашим принципам инкапсуляции и использовать метод добавления элементов в список. Вы ограничили доступ к вашему списку, сделав его private
чтобы другие классы не могли напрямую обращаться к типу данных.
пусть класс, который хранит свой ArrayList
имеют прямой доступ к списку, но, когда другие классы хотите добавить в список, используйте add()
метод.
как только у вас есть Collection
любого рода, как правило, неплохо добавить такие методы, как add()
, remove()
к интерфейсу вашего класса, если имеет смысл, что клиенты могут добавлять или удалять объекты из вашего личного списка.
причина, почему полезно иметь эти дополнительные методы реализованы (это может показаться излишним, потому что после всех этих методов в основном просто вызвать метод на Collection
) заключается в том, что вы защищаете злых клиентов от того, что вы делаете в своем списке не хочу их делать, потому что интерфейс большинства Collection
s содержат больше, чем просто add()
и remove()
методы и в основном, вы не хотите, чтобы клиенты возились с вещами, которые вы не можете контролировать. Поэтому принцип инкапсуляции очень важен для вашего учителя.
еще один плюс: если в любое время вы решите, что определенное условие должно быть выполнено, когда объект добавлен в ваш список, это может быть легко реализовано в методе, который у вас уже есть. Если вы даете клиентский доступ к прямой ссылке вашего списка, это совсем не просто реализовать такого рода вещи (которые не редкость).
надеюсь, что это помогает
это зависит от применения - оба приемлемы. Внимательно посмотрите на класс, который вы пишете, и решите, хотите ли вы разрешить пользователям прямой доступ к содержимому списка или предпочитаете, чтобы они сначала прошли какой-то промежуточный процесс.
например, скажем у вас есть класс ListEncrypter
, который держит ваш MyLinkedList
список. Целью этого класса является шифрование всего, что хранится в MyLinkedList
. В этом случае вы хотите предоставить пользовательский метод add в чтобы обработать добавленный элемент перед размещением его в списке, а также если вы хотите получить доступ к элементу, вы также обработаете его:
public void add(Object element)
{
MyLinkedList.add(encrypt(element););
}
public Object get(int index)
{
return decrypt(MyLinkedList.get(index););
}
в этом случае вы явно хотите запретить пользователю доступ к MyLinkedList
переменная, так как содержимое будет зашифровано, и они ничего не смогут с ним сделать.
С другой стороны, если вы на самом деле не делаете никакой обработки данных (и вы уверены, что вам никогда не понадобится в будущем), вы можете пропустить создание специализированных методов и просто позволить пользователю получить прямой доступ к списку через get
метод.
если я правильно понял ваш вопрос, у вас есть класс, содержащий List
(вероятно, это должно быть final
, но вы не упоминаете об этом), и вы хотите разрешить абонентам добавлять в List
, но не в состоянии заменить его.
вы можете либо предоставить геттер для списка:
public List<E> getMyList() {
return myList;
}
или предоставить метод для добавления в этот список:
public void addToMyList(E e) {
myList.add(e);
}
оба являются действительными проектными решениями, но которые вы используете, будут зависеть от вашего варианта использования. Первый вариант абонентам прямой доступ к List
, эффективно делая его публичным. Это полезно, когда пользователи будут изменять и работать со списком неоднократно, но может быть проблематичным, поскольку вы больше не можете доверять List
находится в любом надежном состоянии (вызывающий может очистить его, или переупорядочить его, или даже злонамеренно вставить объекты другого типа). Поэтому первый вариант следует использовать только тогда, когда вы намерены доверять вызывающему абоненту.
второй вариант дает вызывающему меньше мощности, потому что они могут!--18-->только добавить по одному элементу за раз. Если вы хотите предоставить дополнительные функции (вставка, добавить все и т. д.) вам придется сворачивать каждую операцию по очереди. Но это дает вам больше уверенности, так как вы можете быть уверены List
изменяется только так, как вы одобряете. Этот последний вариант также скрывает (инкапсулирует) детали реализации, которые вы используете List
вообще, поэтому, если инкапсуляция важна для вашего варианта использования, вы хотите пойти этим путем, чтобы избежать разоблачение ваших внутренних структур данных и только разоблачение поведение вы хотите предоставить пользователям.