Что такое неизменность и почему я должен беспокоиться об этом? - PullRequest
56 голосов
/ 08 марта 2009

Я прочитал пару статей об неизменности, но все еще не очень хорошо следую концепции.

Недавно я создал тему, в которой упоминается неизменность, но поскольку это сама по себе тема, сейчас я создаю отдельную тему.

Я упоминал в прошлой ветке, что думал, что неизменность - это процесс создания объекта только для чтения и придания ему низкой видимости. Другой участник сказал, что это не имеет к этому никакого отношения. Эта страница (часть серии ) использует пример неизменяемого класса / структуры и использует только для чтения и другие концепции для его блокировки.

Что такое определение состояния в случае этого примера? Государство - это концепция, которую я не совсем понял.

С точки зрения руководства по проектированию неизменным должен быть класс, который не принимает вводимые пользователем данные и действительно будет просто возвращать значения?

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

Ответы [ 15 ]

1 голос
/ 08 марта 2009

Создание вещей неизменяемыми предотвращает большое количество распространенных ошибок.

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

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

Делая вещи неизменными, вы не должны помнить (или тратить время / память) на создание оборонительных копий.

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

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

0 голосов
/ 02 января 2018

Неизменность - это ценности, а ценности - факты. Нечто имеет значение, если оно не изменится, потому что если что-то можно изменить, это означает, что с ним нельзя связать какое-либо конкретное значение. Объект был инициализирован с состоянием A и во время выполнения программы был преобразован в состояние B и состояние C. Это означает, что объект не представляет отдельное конкретное значение, а представляет собой только контейнер, абстракцию на месте в памяти, и ничего более. Вы не можете доверять такому контейнеру, вы не можете поверить, что этот контейнер имеет значение, которое, как вы полагаете, должно иметь.

Перейдем к примеру - давайте представим, что в коде создается экземпляр класса Book.

Book bookPotter =  new Book();
bookPotter.setAuthor('J.K Rowling');
bookPotter.setTitle('Harry Potter');

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

Book bookLor =  bookPotter; // only reference pass
bookLor.setAuthor('J.R.R Tolkien');
bookLor.setTitle('Lords of The Rings');

Не обманывайтесь разными именами переменных, на самом деле это один и тот же экземпляр. Код снова использует сеттеры на том же экземпляре. Это означает, что bookPotter никогда не был книгой о Гарри Поттере, а bookPotter - только указатель на место, где находится неизвестная книга. Тем не менее, похоже, что это больше полка, чем книга. Какое доверие вы можете иметь к такому объекту? Это книга о Гарри Поттере или книга о LoR или нет?

Изменяемый экземпляр класса - это только указатель на неизвестное состояние с характеристиками класса.

Как тогда избежать мутации? Это довольно просто в правилах:

  • создание объекта с требуемым состоянием через конструктор или конструктор
  • не создавать сеттеры для инкапсулированного состояния объекта
  • не изменять никакое инкапсулированное состояние объекта ни в одном из его методов

Эти несколько правил позволят иметь более предсказуемые и более надежные объекты. Вернемся к нашему примеру и закажем следующие правила:

Book bookPotter =  new Book('J.K Rowling', 'Harry Potter');
Book bookLor = new Book('J.R.R Tolkien', 'Lord of The Rings');

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

Если вы заинтересованы в более широкой области неизменяемости, в этой средней статье больше о предмете по отношению к JavaScript - https://medium.com/@macsikora/the-state-of-immutability-169d2cd11310.

0 голосов
/ 09 апреля 2009

Извините, почему неизменяемость предотвращает состояние гонки (в этом примере пишите после опасности чтения)?

shared v = Integer(3)
v = Integer(v.value() + 1) # in parallel
0 голосов
/ 08 марта 2009

Пример потенциальных преимуществ производительности, предлагаемых неизменяемыми объектами, доступен в WPF API. Общий базовый класс многих типов WPF - Freezable.

В нескольких примерах WPF предполагается, что блокирование объектов (делая их неизменяемыми во время выполнения) может значительно повысить производительность приложения, поскольку блокировка и копирование не требуются.

Лично я хотел бы, чтобы понятие неизменности было проще выразить на языке, который я использую чаще всего, C #. Для полей доступен модификатор readonly. Я хотел бы также видеть модификатор readonly для типов, который будет разрешен только для типов, которые имеют только поля только для чтения, которые имеют типы только для чтения. По сути, это означает, что все состояния должны быть введены во время создания, и что весь граф объектов будет заморожен. Я полагаю, что если эти метаданные присущи CLR, то их можно легко использовать для оптимизации анализа мусора для GC.

0 голосов
/ 08 марта 2009

Смотри, я не читал ссылки, которые ты выложил.

Однако, вот мое понимание.
Каждая программа обладает определенными знаниями о своих данных (состоянии), которые могут изменяться либо пользовательским вводом / внешними изменениями и т. Д.

Переменные (значения, которые меняются) сохраняются для поддержания состояния. Неизменный означает некоторые данные, которые не меняются. Вы можете сказать, что это то же самое, что и readonly, или какое-то постоянное (это можно увидеть так).

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

.net имеет строковый класс, который является примером.
то есть вы не можете изменить строку вместо нее

string s = "hello"; Я могу написать s.Replace ("el", "a"); Но это не изменит содержимое переменной s.

Что я могу сделать, так это s = s.Replace ("el", "a");
Это создаст новую переменную и присвоит ее значение s (перезаписывая содержимое s).

Эксперты могут исправить ошибки, если у меня есть, в моем понимании.

РЕДАКТИРОВАТЬ: Неизменяемый = Невозможно назначить, если он содержит какое-то значение и не может быть заменен на месте (возможно?)

...