Неправильная практика добавления элементов в список с использованием метода getter в java?

Предположим, что у меня есть private ArrayList или LinkedList внутри класса, что я никогда не буду назначать ему новую ссылку, иначе говоря это никогда не произойдет:

myLinkedList = anotherLinkedList;

Так что мне не нужно будет использовать setMyLinkedList(anotherLinkedList).

Но! Мне нужно добавить к нему элементы или удалить из него элементы.

  • Должен ли я писать только новый тип setter, выполняйте задачу adding вместо setting, например myLinkedList.add(someElement)?

  • Или это нормально делать, используя getter, не нарушая принципализацию Encapsulation?

    getMyLinkedList().add(someElement)

(+ Предположим, что я потеряю свою метку, если я не подчиняюсь инкапсуляции: - ")

Ответы

Ответ 1

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

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);
    }
}

EDIT После рассмотрения ваших комментариев я хотел добавить немного о вашей идее сеттера:

Я имел в виду использование этой строки кода внутри нового типа сеттера внутри самого класса, например, public void setter (someElement) {this.myLinkedList.add(someElement);}

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

Ответ 2

В общем, вы не должны предполагать, что список, возвращаемый получателем, является исходным. Например, он может быть украшен или проксирован. Если вы хотите, чтобы на целевом объекте был установлен новый список, вы можете определить метод add в целевом классе.

Ответ 3

Я бы предложил в этом случае лучше всего следовать принципам Encapsulation и использовать метод добавления элементов в список. Вы ограничили доступ к своему списку, сделав его private чтобы другие классы не могли напрямую обращаться к типу данных.

Пусть класс, в котором хранится ваш ArrayList имеет прямой доступ к списку, но когда другие классы хотят добавить в список, используйте метод add().

Ответ 4

Как только у вас есть Collection любого типа, обычно неплохо было бы добавлять такие методы, как add(), remove() в интерфейс вашего класса, если имеет смысл, что клиенты могут добавлять или удалять объекты из вашего личного списка,

Причина, по которой полезно использовать эти дополнительные методы (это может показаться излишним, потому что после того, как все эти методы в основном просто называют метод в Collection) заключается в том, что вы защищаете злых клиентов от того, чтобы делать что-то в своем списке, который вам не нужен они должны делать, потому что интерфейс большинства Collection содержит больше, чем просто методы add() и remove() и в основном, вы не хотите, чтобы клиенты возились с вещами, которые вы не можете контролировать. Поэтому принцип инкапсуляции важен для вашего учителя.

Еще один плюс: если в любое время вы решите, что определенное условие должно выполняться, когда объект добавляется в ваш список, это может быть легко реализовано в методе, который у вас уже есть. Если вы даете клиенту доступ к прямой ссылке вашего списка, совсем не легко реализовать такие вещи (что не редко).

Надеюсь это поможет

Ответ 5

Если я правильно понимаю ваш вопрос, у вас есть класс, содержащий List (он, вероятно, должен быть final, но вы не упомянули об этом), и вы хотите разрешить вызывающим абонентам добавлять в List, но не можете его заменить.

Вы можете либо предоставить getter для списка:

public List<E> getMyList() {
  return myList;
}

Или укажите способ добавления в этот список:

public void addToMyList(E e) {
  myList.add(e);
}

Оба являются действительными проектными решениями, но которые вы используете, будут зависеть от вашего варианта использования. Первый вариант дает абонентам прямой доступ к List, что делает его общедоступным. Это полезно, когда пользователи будут многократно изменять и работать с этим списком, но могут быть проблематичными, поскольку вы больше не можете доверять List в любом виде надежного состояния (вызывающий может его удалить или изменить или даже злонамеренно вставить объекты другого типа). Поэтому первый вариант должен использоваться только тогда, когда вы намерены доверять вызывающему.

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

Ответ 6

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

Например, скажем, у вас есть класс ListEncrypter который содержит список MyLinkedList. Цель этого класса - шифровать все, что хранится в MyLinkedList. В этом случае вы хотите предоставить настраиваемый метод добавления для обработки добавленного элемента перед его помещением в список, и если вы хотите получить доступ к элементу, вы также обработали его:

public void add(Object element)
{
    MyLinkedList.add(encrypt(element););
}

public Object get(int index)
{
    return decrypt(MyLinkedList.get(index););
}

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

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