Что такое государство, изменчивое состояние и неизменное состояние?

32

Это вопрос новичка, но я не смог найти достаточно ответа новичка в Google.

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

Кроме того, что такое изменчивое и неизменное состояние - опять же, как правило, в программировании, а также конкретно в ООП?

Авив Кон
источник
4
Поделиться своими исследованиями помогает всем . Расскажите нам, что вы пробовали и почему это не соответствует вашим потребностям. Это свидетельствует о том, что вы потратили время, чтобы попытаться помочь себе, избавляет нас от повторения очевидных ответов и, прежде всего, помогает получить более конкретный и актуальный ответ. Также см. Как спросить
Гнат

Ответы:

46

У вас есть состояние, когда вы связываете значения (числа, строки, сложные структуры данных) с идентификатором и моментом времени.

Например, число 10 само по себе не представляет никакого состояния: это просто четко определенное число, которое всегда будет само собой: натуральное число 10. В качестве другого примера, строка «HELLO» представляет собой последовательность из пяти символов, и это полностью описано символами, которые это содержит и последовательность, в которой они появляются. Через пять миллионов лет строка «HELLO» по-прежнему будет строкой «HELLO»: чистое значение.

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

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

("colour", "blue")

к моей машине. Пара («цвет», «синий») - это чистая величина, описывающая состояние этого конкретного автомобиля.

Состояние связано не только с конкретным объектом, но и с конкретным моментом времени. Итак, можно сказать, что сегодня моя машина имеет состояние

("colour", "blue")

Завтра я буду перекрашивать его в черный цвет, и новое состояние будет

("colour", "black")

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

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

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

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

Преимущества / недостатки двух подходов

  • Подход 1 потребляет меньше памяти и позволяет создавать новый снимок более эффективно, поскольку он не требует копирования.
  • Подход 1 неявно передает новое состояние всем частям программы, содержащим ссылку на него, при подходе 2 потребуется некоторый механизм для передачи моментального снимка своим наблюдателям, например, в форме события.
  • Подход 2 может помочь предотвратить несогласованные ошибки состояния (например, частичные обновления состояния): определив явную функцию, которая создает новое состояние из старого, легче различить моментальные снимки, созданные в разные моменты времени.
  • Подход 2 является более модульным в том смысле, что он позволяет легко создавать представления о состоянии, которые не зависят от самого состояния, например, с использованием функций более высокого порядка, таких как mapи filter.
Джорджио
источник
1
Обратите внимание, что объекты не единственные вещи с состоянием. Если программа использует (изменяемые) глобальные переменные, говорят, что сама программа имеет состояние. Аналогично, если у функции есть переменная, которая запоминает значения при каждом вызове функции, функция имеет статус.
Доваль
2
@Doval: Вы можете думать о глобальном государстве как о состоянии глобального объекта мира. Насколько я знаю, это представление используется, например, в Ruby. Функция, которая запоминает состояние, изоморфна объекту только одним методом. Общая основная идея заключается в том, что вы связываете значения с идентичностями или местами, то есть определенные вещи могут содержать значения (возможно, изменяемые значения), но сохраняют свою идентичность.
Джорджио
3
Конечно, я согласен в принципе. Я просто уверен, что Prog понимает, что состояние не является чем-то исключительным для ООП. Я не думаю, что мышление «все является объектом» естественно.
Доваль
@Doval: Вы упомянули функции с состоянием, которые запоминают значения в разных вызовах. Одним примером, который я могу вспомнить, являются статические локальные переменные в C. Другой пример - замыкания (функции, которые захватывают переменные, определенные в их контексте). Замыкания в некоторой степени двойственны объектам: замыкание - это объект с ровно одним методом, тогда как объект - это совокупность замыканий, определенных для одних и тех же переменных. Вы, наверное, знаете все это, но я хотел бы подвести итог здесь. Как правило, вы можете хранить состояние в некотором месте памяти и получать к нему доступ, используя разные механизмы, как вы указали.
Джорджио
11

Состояние - это просто информация о чем-то, что хранится в памяти.

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

Изменяемое состояние - это состояние, которое можно изменить после создания объекта (cookie). Неизменное состояние - это состояние, которое нельзя изменить.

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

В общем, состояние объекта хранится в «закрытых переменных или переменных-членах» и доступно через «свойства» или методы получения / установки.

Роберт Харви
источник
3
В интересах Prog тот факт, что значение никогда не изменяется, также важен, потому что его гораздо проще рассуждать. Он может использоваться в любом количестве функций / методов, как вы хотите, и вы знаете, что они не могут его изменить. С изменяемым состоянием вы должны отслеживать историю того, как этот объект использовался, чтобы выяснить, каково его значение сейчас . Это лишние умственные затраты, если сделать его неизменным не усложнит программу.
Доваль
Спасибо за ответ. Таким образом, в основном, в ООП, когда кто-то говорит «состояние», они обычно означают «переменные-члены объекта»? Если это так, то 'изменяемое состояние' - это общедоступные переменные или, более часто, в ООП, закрытые переменные, которые можно изменить с помощью методов установки - в то время как «неизменяемое состояние» - это просто закрытые переменные-члены?
Авив Кон
1
Неизменность можно смоделировать , просто никогда не записывая приватные члены объекта, когда они заполнены начальными значениями. Неизменность может быть реализована с использованием ряда методов: не предусматривается метод сеттера, требуется задание начального значения с помощью параметра конструктора, запись в функциональном стиле, использование констант и т. Д.
Роберт Харви,
1
Я думаю о государстве как о значении некоторой собственности какого-либо лица. «Отправлено» - это состояние. Так же как и «Налоговая ставка». Вес чего-то - это состояние. Бодрствуете ли вы сейчас или спите - это состояние. Цвет чего-то - это состояние. Значимая информация о чем-то, хранящаяся в какой-то компьютерной памяти.
Роберт Харви
1
Во многих языках неизменность может быть обеспечена путем объявления переменных-членов как «const» или «final». Такие переменные могут быть инициализированы только конструктором. Не думайте, что частные переменные являются неизменяемыми - они все еще могут быть изменены собственными функциями-членами класса (методами).
Симон Б
7

Я думаю, что термин «состояние» (в отличие от конкретного типа состояния, такого как «переменная-член») наиболее полезен при сравнении API с состоянием и без состояния. Попытка определить «состояние» без упоминания API-интерфейсов напоминает попытку определить «переменную» или «функцию» без упоминания языков программирования; большинство правильных ответов имеют смысл только для людей, которые уже знают, что означают слова.

Stateful vs Stateless

  • Отслеживание состояния API является тот , который «помнит» , какие функции вы назвали до сих пор и с какими аргументами, поэтому в следующий раз при вызове функции он собирается использовать эту информацию. Часть «запоминания» часто реализуется с помощью переменных-членов, но это не единственный способ.
  • Без гражданства API является один , где каждый вызов функции не зависит только от аргументов , переданных ему, и ничего другого.

Например, OpenGL, пожалуй, самый динамичный API из всех, что я знаю. Если я могу на мгновение смешно упрощать это, мы можем сказать, что это выглядит примерно так:

glSetCurrentVertexBufferArray(vba1);
glSetCurrentVertexBufferObject(vbo1);
glSetCurrentVertexShader(vert1);
glSetCurrentFragmentShader(frag1);
// a dozen other things
glActuallyDrawStuffWithCurrentState(GL_TRIANGLES);

Почти каждая функция просто используется для передачи в какое-то состояние, которое необходимо запомнить OpenGL, затем в конце вы вызываете одну антиклиматически простую функцию, чтобы выполнить весь рисунок.

Версия (без упрощения) OpenGL, скорее всего, будет выглядеть примерно так:

glActuallyDrawStuff(vba1, vbo1, vert1, frag1, /* a dozen other things */, GL_TRIANGLES);

Вы будете часто слышать, как люди говорят, что API с меньшим количеством состояний легче рассуждать. Если вы можете контролировать количество аргументов, я в целом согласен с этим.

Изменчивый против неизменного

Насколько я знаю, это различие имеет смысл только тогда, когда вы можете указать начальное состояние . Например, используя конструкторы C ++:

// immutable state
ImmutableWindow windowA = new ImmutableWindow(600, 400);
windowA = new ImmutableWindow(800, 600); // to change the size, I need a whole new window

// mutable state
MutableWindow windowB = new MutableWindow(600, 400);
windowB.width = 800; // to change the size, I just alter the existing object
windowB.height = 600;

Было бы сложно реализовать класс окна, который не «запоминает», какой у него размер, но вы можете решить, сможет ли пользователь изменить размер окна после его создания.

PS В ООП это правда, что «состояние» обычно означает «переменные-члены», но это может быть намного больше, чем это. Например, в C ++ метод может иметь статическую переменную, а лямбда-выражения могут стать замыканиями при захвате переменных. В обоих случаях эти переменные сохраняются при множественных вызовах функции и, следовательно, могут рассматриваться как состояние. Локальные переменные в обычной функции также могут рассматриваться как состояние в зависимости от того, как они используются (те, которые у меня есть в main (), часто считаются).

Ixrec
источник
УДИВИТЕЛЬНЫЙ ответ. Большое вам спасибо, вы действительно помогли мне быстро это выяснить. Мало ли я знал, я работал с этим в течение длительного времени и не знал, как это называется.
the_endian
2

По словам непрофессионала

В словаре говорится:

а. Состояние или способ существования, как в отношении обстоятельств.

  1. состояние - то, как что-то относится к его основным атрибутам;

Состояние чего-либо - это набор значений, которые его атрибуты имеют в любой данный момент.

В ООП состояние объекта - это моментальный снимок значений его атрибутов в любой данный момент.

Thing t = new Thing();
t.setColor("blue");
t.setPrice(100)
t.setSize("small");

Состояние этого цвета - синий, цена - 100, а размер - маленький.

Если вы позже сделаете:

t.setColor("red");

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

Иногда классы разрабатываются так, что значения их свойств не могут быть изменены после его создания. Все значения их свойств либо передаются в конструктор, либо читаются из какого-либо источника, такого как база данных или файл, но нет никакого способа изменить эти значения после этого момента, так как нет методов «установщика» или любого другого способа изменение значений внутри объекта.

Thing t = new Thing("red",100,"small");
t.setColor("blue") -->> ERROR, the programmer didn't provide a setter or any other way to change the properties values after initialization.

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

Thing t = new Thing("red",100,"small");
t = new Thing("blue",100,"small");
// I had to create a new Thing with another color since this thing is inmutable.
Тулаинс Кордова
источник