Objeto inmutable
# Objeto inmutable

En programación orientada a objetos y programación funcional un «objeto inmutable» es un objeto cuyo estado no puede ser modificado una vez creado. Es el opuesto a los «objetos mutables», que pueden ser modificados tras su creación. En algunos casos un objeto puede ser considerado como inmutable aunque algunos de sus atributos internos cambie, siempre y cuando el estado del objeto parezca no cambiar desde un punto de vista externo al mismo. Por ejemplo, un objeto que use memoización para cachear los resultados de cálculos costosos puede ser considerado un objeto inmutable.

Los objetos inmutables suelen ser útiles dado que son seguros en entornos multihilo. Otro beneficio es que son más fáciles de entender y razonar sobre ellos además de que ofrecen mayor seguridad que los objetos mutables.

## Trasfondo

En programación imperativa, los valores almacenados en variables cuyo contenido no cambia son conocidas como «constantes» para diferenciarlos de los valores que pueden ser alterados en tiempo de ejecución. Ejemplos de constantes serían constantes matemáticas, constantes físicas, factores de conversión o el valor de Pi con varios decimales.

En muchos lenguajes de programación orientada a objetos, se pueden utilizar alias a otros objetos, que suelen ser conocidos como referencias. Algunos ejemplos de estos lenguajes son Java, C++, C#, VB.NET, y varios lenguajes de programación interpretados como Python y Ruby. En el caso de usar referencias, la inmutabilidad de un objeto es importante cuando puede ser referenciado desde diferentes puntos del programa.

Dado que el tamaño de una referencia es en general menor que el objeto al que apunta (es habitual que las referencias tengan el tamaño de un puntero), si se tiene la seguridad de que un objeto es inmutable, este puede ser copiado de manera sencilla creando una referencia al mismo en lugar de copiar el objeto al completo, esto resulta en un ahorro de memoria y una notable mejora en la velocidad de ejecución del programa.

Copiar objetos mediante referencias es más difícil cuando se hace sobre objetos mutables, ya que si cualquier referencia a un objeto mutable cambia el objeto referenciado, el resto de referencias al objeto verán dicho cambio. Si este no es el efecto deseado, puede ser difícil notificar a las otras referencias cómo responder correctamente. En estas situaciones copiar el objeto al completo en lugar de copiar la referencia es una solución más fácil pero más costosa. El patrón de diseño conocido como observer (observador) es una alternativa para controlar cambios sobre objetos mutables.

Los objetos inmutables pueden ser útiles en aplicaciones multihilo ya que diferentes hilos pueden interactuar con los datos contenidos en los objetos inmutables sin preocuparse de que dichos datos vayan a ser cambiados en otros hilos. En consecuencia, los objetos inmutables son considerados más seguros entre hilos que los objetos mutables.

La práctica de usar referencias a objetos en lugar de copias del objeto original recibe el nombre de interning. Usando interning, dos objetos se consideran iguales si y sólo si sus referencias (habitualmente representadas como números enteros) son iguales. Algunos lenguajes como Python hacen esta comparación automáticamente. Si el algoritmo que implementa el interning garantiza su utilización en todo caso que sea posible, entonces el coste de comparar la igualdad de dos objetos se reduce a comparar sus referencias (lo que supone una ganancia de velocidad sustancial en muchas aplicaciones, ya que las referencias suelen implementarse mediante punteros). El interning generalmente sólo es útil para objetos inmutables.

En ocasiones, algunos de los campos de un objeto son inmutables. Es decir, esas partes del objeto no pueden ser cambiadas independientemente de que otras partes del mismo objeto sean modificables (este tipo de objetos se denominan débilmente inmutables). Si todos los campos de un objeto son inmutables, entonces el objeto completo puede considerarse inmutable. Si además el objeto no permite ser ampliado, es considerado fuertemente inmutable. Esto permite forzar explícitamente ciertas invariantes sobre datos concretos en el objeto que se mantendrán sin cambios durante todo el ciclo de vida del mismo. En algunos lenguajes este comportamiento se consigue con el uso de una palabra clave (como const en C++, final en Java) que indica que el campo será inmutable. En otros lenguajes, sucede al contrario: en OCaml los campos de un objeto o registro son inmutables por defecto y necesitan ser declarados con la palabra clave mutable para permitir su modificación.

## Implementación

La inmutabilidad no implica que el objeto sea almacenado en memoria de sólo lectura. Se trata más bien de una orden para que el compilador verifique las operaciones sobre el objeto y aborte la generación del programa en caso de que no se cumpla la inmutabilidad. Es decir, indica lo que el programador debe hacer a través de la interfaz normal del objeto, no necesariamente lo que puede hacer (por ejemplo, se puede dar un rodeo para engañar al sistema de tipos o violar la correctitud de constantes en C o C++).

### Ada

En Ada, cualquier objeto se declara como variable (es decir: mutable, que es implícito por defecto), o constante (es decir: inmutable) mediante la palabra clave constant.

Los parámetros son inmutables cuando se pasan como in y mutables en los modos in out y out.

### C++

En C++ los objetos que cumplen con la correctitud de constantes permiten al usuario declarar instancias tanto mutables como inmutables, a su vez, estos objetos proporcionarán dos versiones de los métodos de acceso a datos, dependiendo de si el objeto es mutable o inmutable se usará una u otra. Un ejemplo de esta funcionalidad es el operador de acceso a elementos operator de la clase vector de la Biblioteca estándar de C++.

Si el objeto proporciona un campo de tipo puntero o referencia a otro objeto, entonces es posible modificar el objeto apuntado o referenciado desde un método constante, sin incumplir la correctitud de constantes. Podría decirse que en ese caso el objeto no es realmente inmutable.

C++ además provee inmutabilidad abstracta mediante la palabra clave mutable, que permite modificar un campo desde un método constante. Uno de los usos habituales de mutable es crear una clase que calcula un valor la primera vez que este es solicitado y a continuación almacena el resultado.

### Java

El típico ejemplo de objetos inmutables en Java, son las instancias de la clase String.

El método toLowerCase no cambiará los datos "ABC" contenidos en la cadena caracteres, en vez de eso, se crea un nuevo objeto String el cual recibe "abc" durante su construcción y se devuelve una referencia a este desde el método toLowerCase. Para hacer que caracteres contenga la cadena "abc" es necesaria otra aproximación:

De esta manera caracteres referencia a un nuevo objeto String cuyo contenido es ”abc”. Nada en la declaración de la clase String indica que deba ser un objeto inmutable; más bien, ninguno de los métodos de la clase modifican en ningún momento los datos que contiene, haciendo que sea inmutable.

La palabra clave final se usa para implementar objetos inmutables, pero por sí misma no puede hacer que otros objetos lo sean. Como por ejemplo:

Podemos evitar que los tipos de datos primitivos (int, long, short, etc.) puedan ser re-asignados una vez definidos:

Los objetos referenciados no pueden hacerse inmutables únicamente usando la palabra clave final, tan sólo previene su reasignación.

Las clases que envuelven tipos primitivos (Integer, Long, Short, Double, Float, Character, Byte, Boolean) son todas inmutables. Las clases Inmutables pueden ser implementadas siguiendo unas directrices simples.

### Perl

En Perl, crear una clase inmutable requiere dos pasos: en primer lugar crear métodos de acceso (ya sea automática o manualmente) que prevengan la modificación de los atributos del objeto, y en segundo lugar, prevenir la modificación directa de los datos de las instancias de dicha clase (que generalmente se almacenan en un hash, y pueden ser bloqueadas con la función lock_hash de Hash::Util):

O con un constructor creado por el programador:

### Python

En Python, algunos tipos primitivos(números, booleanos, cadenas, tuples, frozensets) son immutables, pero las clases creadas por el usuario son en general mutables. Para simular immutabilidad en una clase, se deben sobreescribir las características y borrado del atributo para activar excepciones:

### JavaScript

En JavaScript, algunos de los tipos integrados del lenguaje (números o cadenas de caracteres) son inmutables, pero las clases generadas por el programador son normalmente mutables. Para simular inmutabilidad en una clase, se deben establecer propiedades inmutables al prototipo del objeto:

### Racket

Racket difiere sustancialmente de otras implementaciones de Scheme ya que sus estructuras de datos son inmutables. Adicionalmente, proporciona datos mutables mediante mcons, mcar, set-mcar! etc. Además, soporta varios tipos inmutables, como cadenas de caracteres o vectores, que son usados habitualmente. Las nuevas estructuras son inmutables por defecto, a no ser que uno de sus campos o la estructura al completo sean declarados como mutables explícitamente:

Este lenguaje también proporciona tablas Hash y diccionarios inmutables.

### Scala

En Scala, cada variable puede ser definida como mutable o inmutable: si se usa la palabra clave val será una variable inmutable, mientras que usando var se declara una variable mutable.

El ejemplo anterior define un objeto inmutable valorMaximo (el tipo entero es deducido en tiempo de compilación) y otro objeto mutable valorActual.

Cabe destacar que aunque una variable inmutable no pueda ser reasignada, puede referenciar a un objeto mutable y sería posible llamar métodos mutables sobre dicha variable.

Por defecto, las clases colección son inmutables, por lo que los métodos que actualizan sus valores en realidad devuelven una nueva instancia en lugar de mutar la instancia existente. Este comportamiento puede parecer ineficiente, pero la implementación de estas clases y sus garantías de inmutabilidad permiten que la nueva instancia pueda reutilizar los nodos existentes, los cuales son muy eficientes creando copias.

## Copiar al escribir

Copiar al escribir (CAE), más conocida por su nombre en inglés (Copy-on-write COW), se trata de una técnica que aprovecha las ventajas de los objetos mutables e inmutables, es soportada por casi todo el hardware moderno. Usando esta técnica, cuando un usuario solicita copiar un objeto, el sistema creará en su lugar una referencia al objeto original. En el momento en que el usuario modifica el objeto a través de alguna de sus referencias, el sistema realizará una copia real (a la que aplicará el cambio solicitado) y acto seguido hará que la referencia apunte a este nuevo objeto. El resto de usuarios del sistema no se ven afectados por la operación, ya que aún referencian el objeto original. Por lo tanto, usando CAE, parece que todos los usuarios dispongan de una versión mutable de sus objetos, pero en caso de no modificar dichos objetos las ventajas en ahorro de espacio y mayor velocidad de los objetos inmutables se conservan. Esta técnica es popular en sistemas de memoria virtual ya que permite ahorrar memoria mientras que sigue permitiendo que las aplicaciones funcionen con normalidad.

## Usos

Las Cadena de caracteres y otros objetos suelen ser expresados como objetos inmutables para mejorar su rendimiento en tiempo de ejecución en lenguajes de programación orientada a objetos. En Python, Java y el framework Microsoft .NET, las cadenas de caracteres son objetos inmutables. Tanto Java como el framework Microsoft.NET disponen de versiones mutables de cadenas de caracteres. En Java son StringBuffer y StringBuilder mientras que en.NET es StringBuilder. Python 3 ofrece una cadena de caracteres mutable llamada bytearray. Además, todos los envoltorios de tipos básicos en Java son inmutables.

Se puede forzar el cumplimiento de este patrón de diseño usando compiladores especializados (por ejemplo http://pec.dev.java.net/ (enlace roto disponible en Internet Archive; véase el historial, la primera versión y la última).), y existe una propuesta para añadir tipos inmutables a Java.

Otros patrones de diseño similares son la Interfaz inmutable y el Envoltorio inmutable.

En programación funcional pura no es posible crear objetos mutables, así pues, todos los objetos son inmutables.

