Diferencia entre inmutable y constante


28

A menudo he visto los términos immutabley los he constusado indistintamente. Sin embargo, según mi (poca) experiencia, los dos difieren mucho en el 'contrato' que hacen en el código:

Immutable hace que el contrato indique que este objeto no cambiará (p. Ej., Tuplas de Python, cadenas de Java).

Const hace el contrato de que en el alcance de esta variable no se modificará (no se promete lo que otros hilos podrían hacer al objeto señalado durante este período, por ejemplo, la palabra clave C / C ++).

Obviamente, los dos no son equivalentes, a menos que el lenguaje sea de un solo hilo (PHP), o tenga un sistema de tipeo lineal o uniforme (Clean, Mercury, ATS).

Primero, ¿es correcto mi comprensión de estos dos conceptos?

En segundo lugar, si hay una diferencia, ¿por qué se usan casi exclusivamente como sinónimos?


1
constno existe en todos los idiomas, y la mutabilidad e inmutabilidad no existe en todos los idiomas, por lo que hacer que este lenguaje sea agonístico no es aplicable. Es específico del idioma solo donde se aplican estos conceptos.

2
Lectura relacionada y recomendada: Tipos de inmutabilidad (algunos ejemplos de C #, pero en gran medida independientes del lenguaje). Alguien le da una medalla a Eric Lippert.

Respuestas:


14

Hablaré con C ++, donde esta diferencia es más relevante.

Como observa correctamente, inmutable significa que un objeto no puede cambiar en absoluto después de su creación. Por supuesto, esta creación puede ocurrir en tiempo de ejecución, es decir, un constobjeto no es necesariamente una constante de tiempo de compilación. En C ++, un objeto es inmutable si se cumplen (1) y (2) o (3):

  1. No tiene miembros declarados mutableque estén mutados por constfunciones miembro

  2. Se declara const

  3. constlas funciones de miembro no se utilizan const_castpara eliminar la constcalificación con el fin de mutar a cualquier miembro

Sin embargo, también podría considerar modificadores de acceso: si una operación muta internamente una instancia, pero no tiene ningún efecto sobre el estado de la instancia observable a través de su interfaz pública, entonces el objeto es "lógicamente inmutable".

Por lo tanto, C ++ proporciona las herramientas necesarias para crear objetos inmutables, pero como la mayoría de todo en C ++, las herramientas son mínimamente suficientes y requieren diligencia para su uso real. El estado de una instancia no se limita necesariamente a las variables miembro de la instancia, ya que C ++ no proporciona una forma de imponer la transparencia referencial, también puede incluir el estado global o de clase.

constTambién tiene otra función en C ++: calificar referencias y punteros. Una constreferencia puede referirse a un no constobjeto. Es legal (aunque generalmente no es necesario o aconsejable) usar const_castpara mutar un objeto a través de una constreferencia, si y solo si ese objeto se declara no const:

int        i = 4;         // Non-const object.
const int* p = &i;        // const pointer.

*const_cast<int*>(p) = 5; // Legal.

Y, por supuesto, es un comportamiento indefinido mutar un constobjeto:

const int  i = 4;         // const object.
const int* p = &i;        // const pointer.

*const_cast<int*>(p) = 5; // Illegal.

19

Hablando para Java donde la palabra clave "final" representa "const", considere:

final Person someone = new Person();

Esto significa someoneque NUNCA puede referirse a otro objeto Persona. Pero, aún puede cambiar los detalles de la persona que se refiere. P.ejsomeone.setMonthlySalary(10000);

Pero, si someonefuera un objeto "Inmutable", uno de los siguientes sería verdadero: (a) No tendría un método llamado setMonthlySalary (b) Llamar a setMonthlySalary siempre arrojaría una excepción comoUnsupportedOperationException


10

Los objetos inmutables son aquellos que no cambian de estado después de crearlo. Por ejemplo;

string prefix = "Pre";
string postfix = "Post";
string myComplexStr = prefix + postfix;

En este ejemplo, el objeto myComplexStr es inmutable pero no constante porque se calcula su valor. Y es inmutable porque es una cadena y tiene una propiedad de longitud estática y no puede cambiar.

Los objetos Const generalmente se usan para identificar algunas constantes reales cuyos valores se conocen antes de la compilación como Pi, "USA", "StackOverflow.com", números de puerto, etc.

Desde esta perspectiva, Const es diferente de los objetos inmutables porque el programa no calcula sus valores.

Pero si está hablando de la palabra clave "const" en C ++, puede decir que "const" se usa para crear objetos inmutables.


1
const en C ++ no crea objetos inmutables, es solo un nivel de acceso.
Klaim

¿Puedes explicar cómo "const double pi = 3.14" no es inmutable?
Mert Akcakaya

Bueno, depende de dónde esté. Digamos que hago: "double * p_pi = const_cast <double *> (& pi); * p_pi = 42;" por ejemplo. Entonces, si pi está en el espacio global o en el espacio de nombres, obtengo un error de segmentación, pero creo que es un comportamiento indefinido, no un error específico. Si pi es miembro de algún objeto que está disponible en tiempo de ejecución, que no es estático, obtengo pi == 42. Verá, incluso el uso de mutable está disponible porque const en C ++ se trata de nivel de acceso, semántico, no de inmutabilidad de datos, eso es casi imposible de lograr en C ++. Solo puedes "simularlo". Const no es inmutable.
Klaim

1
@Klaim Mutar un constsimilar es un comportamiento indefinido, sin importar dónde esté asignado, IIRC. Y el comportamiento indefinido es peor que cualquier error específico garantizado. Significa que ya no usa C ++: C ++ no proporciona medios para cambiar un constvalor (excepto los mutablemiembros, por supuesto, pero ese no es su punto), por lo que en lo que respecta a C ++, no puede hacerlo. Lo que las implementaciones específicas permiten es otra cosa completamente distinta (y apuesto a que si compilas con optimizaciones, el truco que realizaste no afectará las expresiones posteriores que utilices piporque ha sido sustituido).

"const en C ++ no crea objetos inmutables" sigue siendo incorrecto porque todavía crea constantes globales como usted indicó en su propia respuesta. La palabra clave es, por supuesto, semántica en algún nivel, de lo contrario, siempre podría cambiar manualmente el voltaje de una celda de memoria y cambiar el valor de un objeto inmutable si está tan ansioso por usar comportamientos indefinidos.
Mert Akcakaya

8

Primero, ¿es correcto mi comprensión de estos dos conceptos?

Sí, pero su segunda pregunta muestra que no comprende estas diferencias.

En segundo lugar, si hay una diferencia, ¿por qué se usan casi exclusivamente como sinónimos?

consten C ++ solo se usa para el nivel de acceso (significa "solo lectura") , no para inmutabilidad. Implica que el acceso en sí está totalmente separado de los datos. Por ejemplo, podría manipular algunos datos y luego exponerlos a través de una referencia constante. El acceso es de solo lectura, pero los datos en sí, ya que todos los datos son mutables.

const solo garantiza las limitaciones de acceso, mientras que la inmutabilidad (como en D por ejemplo) no implica realmente ninguna forma de cambiar los datos en cualquier etapa de la vida del objeto .

Ahora, puede simular la inmutabilidad en C ++ asegurándose de que no se pueda acceder a algunos datos de otra manera que no sea const y asegurarse de que se inicializan y ya no se tocan. Pero esa no es una garantía sólida, ya que los lenguajes como D le dan cuando marca sus datos como inmutables. El lenguaje asegura que no es posible realizar ninguna operación que modifique esos datos, mientras que en C ++ aún puede cambiar los datos a través de la conversión continua y la mutabilidad si es realmente necesario.

Al final, no es lo mismo ya que no ofrece las mismas garantías.


3

Hablando de JavaScript, las palabras clave constyObject.freeze

constse aplica a las fijacionesvariables . Crea un enlace inmutable, no puede asignarle un nuevo valor.

Object.freezetrabaja en valores de objeto. Hace que un objeto sea inmutable . Es decir, no puede cambiar sus propiedades.


0

En C ++ son iguales. Aunque puede cambiar un constobjeto si tiene su ubicación en la memoria y el permiso del sistema operativo para escribir en esa memoria.


1
En realidad, ese es un argumento en contra de que sean los mismos: C ++ simplemente no tiene una palabra clave inmutable o soporte de lenguaje. Y también, supongo que el programador utiliza el lenguaje de una manera sensata: de lo contrario, const tampoco tiene absolutamente ningún valor.
K.Steff

1
@ K.Steff - tal vez sea mejor decir que no hay inmutableidad adicional en C ++ que no sea la proporcionada por const
Martin Beckett

Absolutamente preciso :)
K.Steff

En C ++ no son lo mismo en absoluto. const es un nivel de acceso de "solo lectura", no significa que los datos sean inmutables. Puede omitirlo en C ++, la mayoría de las veces.
Klaim

0

En C, C ++ y lenguajes relacionados, también hay una diferencia entre un objeto que está en constante y su referencia o puntero al objeto que es una referencia constante.

Si intenta modificar un objeto constante, obtiene un comportamiento indefinido. (Puede intentar modificar un objeto constante, por ejemplo, tomando su dirección, convirtiendo la dirección en un puntero no constante y luego utilizando ese puntero no constante para modificar el objeto).

El puntero o referencia constante, por otro lado, solo le dice al compilador que no puede usar este puntero o referencia para modificar el objeto. Puede lanzar el puntero o la referencia e intentar modificar el objeto. Si el objeto en sí era constante, sucederán cosas malas. Si el objeto no era realmente constante, cambiará. Por supuesto, esto puede confundir a los usuarios de su código y posiblemente causar errores.

En C, si utiliza un literal de cadena como "Hola", los cinco caracteres y los bytes cero finales son realmente constantes, pero obtiene un puntero no constante. Muy mala idea usar ese puntero no constante para cambiar el objeto.

En C, puede tener un puntero "const restrict". Eso significa que el objeto señalado es temporalmente constante. Si el objeto se modifica por cualquier medio mientras el puntero "const restrict" está dentro del alcance, obtendrá un comportamiento indefinido. Esto es más fuerte que un puntero constante que solo le impide cambiar un objeto a través de este puntero.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.