O que é Estado, Estado Mutável e Estado Imutável?

32

Esta é uma pergunta para iniciantes, mas não consegui encontrar uma resposta suficiente à prova de novatos no Google.

O que as pessoas querem dizer quando dizem 'estado' - na programação em geral, e na programação OO especificamente?

Além disso, o que é estado mutável e imutável - novamente, geralmente na programação e também especificamente no OOP?

Aviv Cohn
fonte
4
Compartilhar sua pesquisa ajuda a todos . Conte-nos o que você tentou e por que ele não atendeu às suas necessidades. Isso demonstra que você reservou um tempo para tentar ajudar a si mesmo, evita reiterar respostas óbvias e, acima de tudo, ajuda a obter uma resposta mais específica e relevante. Veja também How to Ask
gnat

Respostas:

46

Você tem estado ao associar valores (números, seqüências de caracteres, estruturas de dados complexas) a uma identidade e um ponto no tempo.

Por exemplo, o número 10 por si só não representa nenhum estado: é apenas um número bem definido e sempre será ele mesmo: o número natural 10. Como outro exemplo, a cadeia "HELLO" é uma sequência de cinco caracteres e é completamente descrito pelos caracteres que contém e pela sequência em que aparecem. Daqui a cinco milhões de anos, a string "HELLO" ainda será a string "HELLO": um valor puro.

Para ter estado, você deve considerar um mundo em que esses valores puros estejam associados a algum tipo de entidade que possui uma identidade . Identidade é uma idéia primitiva: significa que você pode distinguir duas coisas, independentemente de outras propriedades que possam ter. Por exemplo, dois carros do mesmo modelo, mesma cor, ... são dois carros diferentes.

Dadas essas coisas com identidade, você pode anexar propriedades a elas, descritas por valores puros. Por exemplo, meu carro tem a propriedade de ser azul. Você pode descrever esse fato associando o par

("colour", "blue")

para o meu carro. O par ("cor", "azul") é um valor puro que descreve o estado desse carro em particular.

O estado não está associado apenas a uma entidade específica, mas também a um momento específico. Então, você pode dizer que hoje, meu carro tem estado

("colour", "blue")

Amanhã vou tê-lo repintado em preto e o novo estado será

("colour", "black")

Observe que o estado de uma entidade pode mudar, mas sua identidade não muda por definição. Bem, desde que a entidade exista, é claro: um carro pode ser criado e destruído, mas manterá sua identidade por toda a vida. Não faz sentido falar sobre a identidade de algo que ainda não existe.

Se os valores das propriedades anexadas a uma determinada entidade mudarem com o tempo, você diz que o estado dessa entidade é mutável . Caso contrário, você diz que o estado é imutável .

A implementação mais comum é armazenar o estado de uma entidade em algum tipo de variável (variáveis ​​globais, variáveis ​​de membros de objetos), ou seja, armazenar o instantâneo atual de um estado. O estado mutável é implementado usando a atribuição: cada operação de atribuição substitui o instantâneo anterior por um novo. Esta solução normalmente usa locais de memória para armazenar o instantâneo atual. Substituir um local de memória é uma operação destrutiva que substitui um instantâneo por um novo. ( Aqui você encontra uma conversa interessante sobre essa abordagem de programação orientada a locais .)

Uma alternativa é visualizar os estados subseqüentes (histórico) de uma entidade como um fluxo (possivelmente sequência infinita) de valores, consulte, por exemplo, o Capítulo 3 do SICP . Nesse caso, cada instantâneo é armazenado em um local de memória diferente e o programa pode examinar diferentes instantâneos ao mesmo tempo. As capturas instantâneas não utilizadas podem ser coletadas como lixo quando não são mais necessárias.

Vantagens / desvantagens das duas abordagens

  • A abordagem 1 consome menos memória e permite construir um novo instantâneo com mais eficiência, pois não envolve cópia.
  • A abordagem 1 empurra implicitamente o novo estado para todas as partes de um programa com uma referência a ele; a abordagem 2 precisaria de algum mecanismo para enviar um instantâneo a seus observadores, por exemplo, na forma de um evento.
  • A abordagem 2 pode ajudar a evitar erros de estado inconsistentes (por exemplo, atualizações parciais de estado): definindo uma função explícita que produz um novo estado a partir de um antigo, é mais fácil distinguir entre os instantâneos produzidos em diferentes momentos no tempo.
  • A abordagem 2 é mais modular, pois permite produzir facilmente visualizações no estado que são independentes do próprio estado, por exemplo, usando funções de ordem superior, como mape filter.
Giorgio
fonte
1
Observe que os objetos não são as únicas coisas com estado. Se um programa usa variáveis ​​globais (mutáveis), diz-se que o próprio programa possui estado. Da mesma forma, se uma função tiver uma variável que se lembre de valores através de chamadas de função, a função é com estado.
Doval
2
@Doval: Você pode pensar no estado global como o estado de um objeto mundial global. Até onde eu sei, essa visão é usada, por exemplo, no Ruby. Uma função que lembra estado é isomórfica para um objeto com apenas um método. A idéia básica comum é que você associe valores a identidades ou lugares, ou seja, que certas coisas possam conter valores (possivelmente valor mutável), mas manter sua identidade.
Giorgio
3
Claro, eu concordo em princípio. Estou apenas certificando-me de que Prog entende que o estado não é algo exclusivo do OOP. Não acho que a linha de pensamento "tudo é um objeto" venha naturalmente.
Doval
@Doval: você mencionou funções com estado que lembram valores em diferentes chamadas. Um exemplo em que posso pensar são variáveis ​​locais estáticas em C. Outro exemplo é o fechamento (funções que capturam variáveis ​​definidas em seu contexto). Os fechamentos são um tanto duplos aos objetos: um fechamento é um objeto com exatamente um método, enquanto um objeto é uma coleção de fechamentos definidos sobre as mesmas variáveis. Você provavelmente sabe tudo isso, mas eu queria resumir aqui. Em geral, você pode armazenar o estado em algum local da memória e acessá-lo usando diferentes mecanismos, como você apontou.
Giorgio
11

Estado é simplesmente informação sobre algo mantido na memória.

Como um simples exercício de orientação a objetos, pense em uma classe como um cortador de biscoitos e cookies como objetos. Você pode criar um cookie (instanciar um objeto) usando o cortador de cookies (classe). Digamos que uma das propriedades do cookie seja sua cor (que pode ser alterada usando corantes alimentares). A cor desse cookie faz parte de seu estado, assim como as outras propriedades.

Estado mutável é o estado que pode ser alterado depois que você cria o objeto (cookie). Estado imutável é um estado que não pode ser alterado.

Objetos imutáveis ​​(para os quais nenhum estado pode ser alterado) tornam-se importantes quando você lida com simultaneidade, a capacidade de mais de um processador no seu computador operar nesse objeto ao mesmo tempo. A imutabilidade garante que você possa confiar no estado para ser estável e válido durante a vida útil do objeto.

Em geral, o estado de um objeto é mantido em "variáveis ​​privadas ou membros" e acessado por meio de "propriedades" ou métodos getter / setter.

Robert Harvey
fonte
3
Para o benefício de Prog, o fato de um valor nunca mudar também é importante porque é muito mais fácil argumentar. Pode ser usado em quantas funções / métodos você desejar e sabe que eles não podem alterá-lo. Com o estado mutável, você precisa acompanhar o histórico de como esse objeto foi usado para descobrir qual é o seu valor agora . Isso é desnecessário sobrecarga mental se torná-lo imutável não complica o programa.
Doval
Obrigado por responder. Então, basicamente, no OOP, quando alguém diz 'estado', geralmente significa "variáveis ​​de membro de um objeto"? Nesse caso, 'estado mutável' são variáveis ​​públicas ou mais comuns em OOP, variáveis ​​privadas que podem ser alteradas por métodos setter - enquanto 'estado imutável' são simplesmente variáveis ​​de membros privadas?
Aviv Cohn
1
A imutabilidade pode ser simulada simplesmente nunca escrevendo para os membros privados de um objeto, uma vez preenchidos com valores iniciais. Imutabilidade pode ser aplicada usando uma série de métodos: não fornecendo um método setter, exigindo o valor inicial a ser definido através de um parâmetro de construtor, escrevendo em um estilo funcional, utilizando constantes, etc.
Robert Harvey
1
Penso em estado como o valor de alguma propriedade de alguma entidade. "Enviado" é um estado. O mesmo acontece com "Taxa de imposto". O peso de algo é um estado. Se você está atualmente acordado ou dormindo é um estado. A cor de algo é um estado. Informações significativas sobre algo, mantidas em algum tipo de memória do computador.
31714 Robert
1
Em muitos idiomas, a imutabilidade pode ser imposta declarando variáveis ​​de membro como "const" ou "final". Tais variáveis ​​podem ser inicializadas apenas pelo construtor. Não assuma que variáveis ​​privadas são imutáveis ​​- elas ainda podem ser modificadas pelas próprias funções de membro da classe (métodos).
Simon B
7

Eu acho que o termo "estado" (em oposição a um tipo concreto de estado, como "variável de membro") é mais útil quando se compara uma API com monitoração de estado com uma sem estado. Tentar definir "estado" sem mencionar APIs é como tentar definir "variável" ou "função" sem mencionar linguagens de programação; a maioria das respostas corretas só faz sentido para pessoas que já sabem o que as palavras significam.

Stateful vs Stateless

  • Uma API stateful é aquela que "lembra" de quais funções você chamou até agora e com quais argumentos; portanto, na próxima vez que você chamar uma função, ela usará essas informações. A parte "lembrar" geralmente é implementada com variáveis ​​de membro, mas essa não é a única maneira.
  • Uma API sem estado é aquela em que toda chamada de função depende apenas dos argumentos passados ​​para ela e nada mais.

Por exemplo, o OpenGL é provavelmente a API mais estável que eu conheço. Se eu simplificamente simplificá-lo por um momento, podemos dizer que é algo como isto:

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

Quase todas as funções são usadas apenas para passar em algum estado em que o OpenGL precisa se lembrar; então, no final, você chama uma função anticlimacticamente simples para fazer todo o desenho.

Uma versão sem estado do OpenGL (simplificado) provavelmente se pareceria com isso:

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

Você sempre ouvirá as pessoas dizerem que as APIs com menos estado são mais fáceis de raciocinar. Se você pode manter a contagem de argumentos sob controle, eu geralmente concordo com isso.

Mutável vs Imutável

Até onde eu sei, essa distinção só é significativa quando você pode especificar um estado inicial . Por exemplo, usando construtores 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;

Seria difícil implementar uma classe de janela que não "lembre" qual é o tamanho, mas você pode decidir se o usuário poderá alterar o tamanho de uma janela após criá-la.

PS No POO, é verdade que "estado" geralmente significa "variáveis-membro", mas pode ser muito mais do que isso. Por exemplo, em C ++, um método pode ter uma variável estática e lambdas podem se tornar encerramentos capturando variáveis. Nos dois casos, essas variáveis ​​persistem em várias chamadas para a função e, portanto, provavelmente se qualificam como estado. Variáveis ​​locais em uma função regular também podem ser consideradas estado, dependendo de como elas são usadas (as que eu tenho em main () costumam contar).

Ixrec
fonte
Resposta INCRÍVEL. Muito obrigado, você realmente me ajudou a entender isso rapidamente. Mal sabia eu, trabalhava com isso há muito tempo e não sabia como era chamado.
the_endian
2

Em palavras leigas

O dicionário declara:

uma. Uma condição ou modo de ser, como no que diz respeito às circunstâncias.

  1. estado - a maneira como algo é em relação aos seus principais atributos;

O estado de algo é o conjunto de valores que seus atributos têm em um determinado momento.

No POO, o estado de um objeto é um instantâneo dos valores de seus atributos em um dado momento.

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

O estado disso é sua cor sendo azul, seu preço sendo 100 e seu tamanho sendo pequeno.

Se você fizer mais tarde:

t.setColor("red");

Você altera um de seus atributos, mas também o estado como um todo, pois o objeto não é mais o mesmo que era.

Às vezes, as classes são projetadas para que os valores de suas propriedades não possam ser alterados após a criação. Todos os valores de suas propriedades são passados ​​para o construtor ou lidos de alguma fonte, como um banco de dados ou um arquivo, mas não há como alterar esses valores após esse momento, pois não existem métodos "setter" ou qualquer outra maneira de alterando os valores dentro do objeto.

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.

Isso é chamado de estado que não pode ser alterado de mutado. Tudo o que você pode fazer é destruir o objeto, criar um novo e atribuí-lo à mesma referência ou variável.

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.
Tulains Córdova
fonte