Неизменяемые предметы против неизменных коллекций
Одним из лучших моментов в дискуссии о изменчивых и неизменных объектах является возможность распространения концепции неизменности на коллекции. Неизменяемый объект - это объект, который часто представляет единую логическую структуру данных (например, неизменяемая строка). Когда у вас есть ссылка на неизменный объект, содержимое объекта не изменится.
Неизменная коллекция - это коллекция, которая никогда не меняется.
Когда я выполняю операцию с изменяемой коллекцией, я изменяю коллекцию на месте, и все сущности, которые имеют ссылки на коллекцию, увидят это изменение.
Когда я выполняю операцию с неизменяемой коллекцией, в новую коллекцию возвращается ссылка, отражающая это изменение. Все объекты, которые имеют ссылки на предыдущие версии коллекции, не увидят изменения.
Умные реализации не обязательно должны копировать (клонировать) всю коллекцию, чтобы обеспечить эту неизменность. Простейшим примером является стек, реализованный в виде односвязного списка, и операции push / pop. Вы можете повторно использовать все узлы из предыдущей коллекции в новой коллекции, добавив только один узел для push и не клонировав ни одного узла для pop. Операция push_tail в односвязном списке, с другой стороны, не так проста и эффективна.
Неизменяемые и изменчивые переменные / ссылки
Некоторые функциональные языки применяют концепцию неизменности к самим ссылкам на объекты, допуская только одно присвоение ссылок.
- В Erlang это верно для всех «переменных». Я могу назначить объекты только один раз. Если бы я работал с коллекцией, я бы не смог переназначить новую коллекцию на старую ссылку (имя переменной).
- Scala также встраивает это в язык, при этом все ссылки объявляются с помощью var или val , причем vals является только одним присваиванием и продвигает функциональный стиль, но vars допускает более C-подобную или Java-подобную структуру программы.
- Требуется объявление var / val, в то время как многие традиционные языки используют необязательные модификаторы, такие как final в java и const в C.
Простота разработки и производительность
Почти всегда причина использования неизменяемого объекта заключается в содействии программированию без побочных эффектов и простым рассуждениям о коде (особенно в среде с высокой степенью параллелизма / параллельности). Вам не нужно беспокоиться об изменении базовых данных другим объектом, если объект неизменен.
Основным недостатком является производительность. Вот описание простого теста, который я провел на Java, сравнивая некоторые неизменяемые и изменяемые объекты в игрушечной задаче.
Проблемы с производительностью спорны во многих приложениях, но не во всех, поэтому многие большие числовые пакеты, такие как класс Numpy Array в Python, допускают обновления больших массивов на месте. Это было бы важно для областей применения, которые используют большие матричные и векторные операции. Эти большие параллельные с данными и вычислительно сложные задачи достигают большого ускорения при работе на месте.
string
является неизменным, по крайней мере, в .NET, и я думаю, во многих других современных языках.