stringtranslate.com

Objeto inmutable

En la programación orientada a objetos (OO) y funcional , un objeto inmutable (objeto inmutable [1] ) es un objeto cuyo estado no se puede modificar después de su creación. [2] Esto contrasta con un objeto mutable (objeto modificable), que se puede modificar después de su creación. [3] En algunos casos, un objeto se considera inmutable incluso si cambian algunos atributos utilizados internamente, pero el estado del objeto parece inmutable desde un punto de vista externo. Por ejemplo, un objeto que utiliza la memorización para almacenar en caché los resultados de cálculos costosos podría seguir considerándose un objeto inmutable.

Las cadenas y otros objetos concretos se expresan normalmente como objetos inmutables para mejorar la legibilidad y la eficiencia en tiempo de ejecución en la programación orientada a objetos. Los objetos inmutables también son útiles porque son inherentemente seguros para subprocesos . [2] Otros beneficios son que son más simples de entender y razonar y ofrecen mayor seguridad que los objetos mutables. [2]

Conceptos

Variables inmutables

En la programación imperativa , los valores contenidos en las variables del programa cuyo contenido nunca cambia se conocen como constantes para diferenciarlos de las variables que podrían modificarse durante la ejecución. Algunos ejemplos incluyen factores de conversión de metros a pies o el valor de pi a varios decimales.

Los campos de solo lectura se pueden calcular cuando se ejecuta el programa (a diferencia de las constantes, que se conocen de antemano), pero nunca cambian después de que se inicializan.

Inmutabilidad débil vs. inmutabilidad fuerte

A veces, se habla de que ciertos campos de un objeto son inmutables. Esto significa que no hay forma de cambiar esas partes del estado del objeto, aunque otras partes del objeto puedan ser cambiables ( débilmente inmutable ). Si todos los campos son inmutables, entonces el objeto es inmutable. Si el objeto completo no puede ser extendido por otra clase, el objeto se llama fuertemente inmutable . [4] Esto podría, por ejemplo, ayudar a imponer explícitamente ciertas invariantes sobre ciertos datos en el objeto que permanecen iguales durante la vida útil del objeto. En algunos lenguajes, esto se hace con una palabra clave (por ejemplo, consten C++ , finalen Java ) que designa el campo como inmutable. Algunos lenguajes lo invierten: en OCaml , los campos de un objeto o registro son inmutables por defecto y deben marcarse explícitamente con mutablepara que lo sean.

Referencias a objetos

En la mayoría de los lenguajes orientados a objetos , se puede hacer referencia a los objetos mediante referencias . Algunos ejemplos de estos lenguajes son Java , C++ , C# , VB.NET y muchos lenguajes de programación , como Perl , Python y Ruby . En este caso, importa si el estado de un objeto puede variar cuando se comparten objetos mediante referencias.

Referenciar vs copiar objetos

Si se sabe que un objeto es inmutable, es preferible crear una referencia a él en lugar de copiar el objeto entero. Esto se hace para conservar memoria al evitar la duplicación de datos y evitar llamadas a constructores y destructores; también da como resultado un aumento potencial en la velocidad de ejecución.

La técnica de copia de referencia es mucho más difícil de utilizar para objetos mutables, porque si cualquier usuario de una referencia de objeto mutable la cambia, todos los demás usuarios de esa referencia ven el cambio. Si este no es el efecto deseado, puede resultar difícil notificar a los demás usuarios para que respondan correctamente. En estas situaciones, la copia defensiva de todo el objeto en lugar de la referencia suele ser una solución fácil pero costosa. El patrón de observador es una técnica alternativa para gestionar los cambios en objetos mutables.

Copiar en escritura

Una técnica que combina las ventajas de los objetos mutables e inmutables , y que está soportada directamente en casi todo el hardware moderno, es la copia en escritura (COW). Con esta técnica, cuando un usuario pide al sistema que copie un objeto, este simplemente crea una nueva referencia que sigue apuntando al mismo objeto. Tan pronto como un usuario intenta modificar el objeto a través de una referencia particular, el sistema hace una copia real, aplica la modificación a esa copia y establece la referencia para que haga referencia a la nueva copia. Los demás usuarios no se ven afectados, porque siguen haciendo referencia al objeto original. Por lo tanto, con COW, todos los usuarios parecen tener una versión mutable de sus objetos, aunque en el caso de que los usuarios no modifiquen sus objetos, se conservan las ventajas de ahorro de espacio y velocidad de los objetos inmutables. La copia en escritura es popular en los sistemas de memoria virtual porque les permite ahorrar espacio en la memoria y al mismo tiempo manejar correctamente todo lo que un programa de aplicación pueda hacer.

Pasantía

La práctica de usar siempre referencias en lugar de copias de objetos iguales se conoce como interning . Si se usa interning, dos objetos se consideran iguales si y solo si sus referencias, típicamente representadas como punteros o números enteros, son iguales. Algunos lenguajes hacen esto automáticamente: por ejemplo, Python interna automáticamente las cadenas cortas . Si se garantiza que el algoritmo que implementa interning lo hará en cada caso en que sea posible, entonces comparar objetos para determinar su igualdad se reduce a comparar sus punteros, una ganancia sustancial en velocidad en la mayoría de las aplicaciones. (Incluso si no se garantiza que el algoritmo sea integral, aún existe la posibilidad de una mejora rápida en el caso de que los objetos sean iguales y usen la misma referencia). El interning generalmente solo es útil para objetos inmutables.

Seguridad de los hilos

Los objetos inmutables pueden ser útiles en aplicaciones multiproceso. Varios subprocesos pueden actuar sobre datos representados por objetos inmutables sin preocuparse de que otros subprocesos modifiquen los datos. Por lo tanto, los objetos inmutables se consideran más seguros para subprocesos que los objetos mutables.

Violando la inmutabilidad

La inmutabilidad no implica que el objeto tal como está almacenado en la memoria de la computadora no se pueda escribir. Más bien, la inmutabilidad es una construcción en tiempo de compilación que indica lo que un programador puede hacer a través de la interfaz normal del objeto, no necesariamente lo que puede hacer de manera absoluta (por ejemplo, eludiendo el sistema de tipos o violando la corrección constante en C o C++ ).

Detalles específicos del idioma

En Python , Java [5] : 80  y .NET Framework , las cadenas son objetos inmutables. Tanto Java como .NET Framework tienen versiones mutables de cadena. En Java [5] : 84  son StringBuffery StringBuilder(versiones mutables de Java String) y en .NET es StringBuilder(versión mutable de .Net String). Python 3 tiene una variante de cadena mutable (bytes), denominada bytearray. [6]

Además, todas las clases contenedoras primitivas en Java son inmutables.

Patrones similares son la Interfaz Inmutable y el Envoltorio Inmutable.

En los lenguajes de programación funcional pura no es posible crear objetos mutables sin extender el lenguaje (por ejemplo, a través de una biblioteca de referencias mutables o una interfaz de función externa ), por lo que todos los objetos son inmutables.

Ada

En Ada , cualquier objeto se declara variable (es decir, mutable; generalmente el valor predeterminado implícito) o constant(es decir, inmutable) mediante la constantpalabra clave.

 tipo  Some_type  es  nuevo  entero ;  -- podría ser cualquier cosa más complicada  x :  constante  Some_type :=  1 ;  -- inmutable  y :  Some_type ;  -- mutable

Los parámetros del subprograma son inmutables en el modo in y mutables en los modos in out y out .

 procedimiento  Hazlo ( a : in  Integer ;  b : in  out  Integer ;  c : out  Integer )  es  begin  -- a es inmutable  b :=  b  +  a ;  c :=  a ;  end  Hazlo ;

DO#

En C# puedes imponer la inmutabilidad de los campos de una clase con la readonlydeclaración. [7] : 239  Al imponer todos los campos como inmutables, obtienes un tipo inmutable.

clase AnImmutableType { público de solo lectura doble _valor ; público AnImmutableType ( doble x ) { _valor = x ; } público AnImmutableType Square () { devolver nuevo AnImmutableType ( _valor * _valor ); } }                             

C# tiene registros que son inmutables. [8] [9]

registrar Persona ( cadena Nombre , cadena Apellido );    

C++

En C++, una implementación de constante-correctaCart permitiría al usuario crear instancias de la clase y luego usarlas como const(inmutables) o mutables, según se desee, proporcionando dos versiones diferentes del items()método. (Observe que en C++ no es necesario —y de hecho es imposible— proporcionar un constructor especializado para constinstancias).

clase Carrito { público : Carrito ( std :: vector < Item > artículos ) : artículos_ ( artículos ) {}        std :: vector < Item >& items () { devolver items_ ; } const std :: vector < Item >& items () const { devolver items_ ; }              int ComputeTotalCost () const { /* devuelve la suma de los precios */ }      privado : std :: vector < Item > items_ ; };  

Tenga en cuenta que, cuando hay un miembro de datos que es un puntero o referencia a otro objeto, entonces es posible mutar el objeto apuntado o referenciado solo dentro de un método no constante.

C++ también proporciona inmutabilidad abstracta (a diferencia de la inmutabilidad bit a bit) a través de la mutablepalabra clave, que permite cambiar una variable miembroconst desde dentro de un método.

clase Carrito { público : Carrito ( std :: vector < Item > artículos ) : artículos_ ( artículos ) {}        const std :: vector < Item >& items () const { return items_ ; }        int ComputeTotalCost () const { if ( costo_total_ ) { return * costo_total_ ; }          int costo_total = 0 ; for ( const auto & item : items_ ) { costo_total += item . Cost (); } costo_total_ = costo_total ; return costo_total ; }                     privado : std :: vector < Item > items_ ; mutable std :: opcional < int > costo_total_ ; };     

D

En D , existen dos calificadores de tipo , consty immutable, para variables que no se pueden cambiar. [10] A diferencia de C++ const, Java finaly C# readonly, son transitivos y se aplican recursivamente a cualquier cosa alcanzable a través de referencias de dicha variable. La diferencia entre consty immutablees a qué se aplican: constes una propiedad de la variable: pueden existir legalmente referencias mutables al valor al que se hace referencia, es decir, el valor puede cambiar realmente. Por el contrario, immutablees una propiedad del valor al que se hace referencia: el valor y cualquier cosa transitivamente alcanzable desde él no pueden cambiar (sin romper el sistema de tipos, lo que lleva a un comportamiento indefinido ). Cualquier referencia a ese valor debe estar marcada consto immutable. Básicamente, para cualquier tipo no calificado T, const(T)es la unión disjunta de T(mutable) y immutable(T).

clase C { /*mutable*/ Objeto mField ; constante Objeto cField ; inmutable Objeto iField ; }           

CEn el caso de un objeto mutable , mFieldse puede escribir en él. En el caso de un const(C)objeto, mFieldno se puede modificar, hereda const; iFieldsigue siendo inmutable, ya que es la garantía más sólida. En el caso de un immutable(C), todos los campos son inmutables.

En una función como esta:

void func ( C m , const C c , immutable C i ) { /* dentro de las llaves */ }          

Dentro de las llaves, cpodría hacer referencia al mismo objeto que m, por lo que las mutaciones a también mpodrían cambiar indirectamente . Además, podría hacer referencia al mismo objeto que , pero como el valor es inmutable, no hay cambios. Sin embargo, y no pueden hacer referencia legal al mismo objeto.ccimi

En el lenguaje de las garantías, mutable no tiene garantías (la función puede cambiar el objeto), constes una garantía solo externa de que la función no cambiará nada y immutablees una garantía bidireccional (la función no cambiará el valor y quien lo llama no debe cambiarlo).

Valores que se inicializan consto immutabledeben inicializarse mediante asignación directa en el punto de declaración o mediante un constructor .

Debido a que constlos parámetros olvidan si el valor era mutable o no, una construcción similar, inout, actúa, en cierto sentido, como una variable para la información de mutabilidad. Una función de tipo const(S) function(const(T))devuelve const(S)valores tipificados para argumentos mutables, constantes e inmutables. Por el contrario, una función de tipo inout(S) function(inout(T))devuelve Spara Targumentos mutables, const(S)para const(T)valores y immutable(S)para immutable(T)valores.

La conversión de valores inmutables a mutables genera un comportamiento indefinido al cambiar, incluso si el valor original proviene de un origen mutable. La conversión de valores mutables a inmutables puede ser legal cuando no quedan referencias mutables posteriormente. "Una expresión puede convertirse de mutable (...) a inmutable si la expresión es única y todas las expresiones a las que se refiere transitivamente son únicas o inmutables". [10] Si el compilador no puede probar la unicidad, la conversión se puede realizar explícitamente y es responsabilidad del programador asegurarse de que no existan referencias mutables.

El tipo stringes un alias para immutable(char)[], es decir, una porción tipificada de memoria de caracteres inmutables. [11] Crear subcadenas es económico, ya que solo copia y modifica un puntero y un campo de longitud, y seguro, ya que los datos subyacentes no se pueden cambiar. Los objetos de tipo const(char)[]pueden hacer referencia a cadenas, pero también a búferes mutables.

Al hacer una copia superficial de un valor constante o inmutable se elimina la capa exterior de inmutabilidad: al copiar una cadena inmutable ( immutable(char[])) se devuelve una cadena ( immutable(char)[]). Se copian el puntero y la longitud inmutables y las copias son mutables. Los datos a los que se hace referencia no se han copiado y mantienen su calificador, en el ejemplo immutable. Se pueden eliminar haciendo una copia más profunda, por ejemplo, utilizando la dupfunción .

Java

Un ejemplo clásico de un objeto inmutable es una instancia de la Stringclase Java

String s = "ABC" ; s . toLowerCase (); // ¡Esto no logra nada!    

El método toLowerCase()no cambia los datos "ABC" que scontiene. En su lugar, se crea una instancia de un nuevo objeto String y se le asignan los datos "abc" durante su construcción. El método devuelve una referencia a este objeto String toLowerCase(). Para que el String scontenga los datos "abc", se necesita un enfoque diferente:

s = s .toLowerCase ( );  

Ahora, la cadena shace referencia a un nuevo objeto String que contiene "abc". No hay nada en la sintaxis de la declaración de la clase String que la imponga como inmutable; más bien, ninguno de los métodos de la clase String afecta los datos que contiene un objeto String, lo que la hace inmutable.

La palabra clave final( artículo detallado ) se utiliza para implementar tipos primitivos inmutables y referencias a objetos, [12] pero no puede, por sí sola, hacer que los objetos sean inmutables. Vea los ejemplos a continuación:

Las variables de tipo primitivo ( int, long, short, etc.) se pueden reasignar después de ser definidas. Esto se puede evitar utilizando final.

int i = 42 ; //int es un tipo primitivo i = 43 ; // OK       final int j = 42 ; j = 43 ; // no compila. j es final, por lo que no se puede reasignar       

Los tipos de referencia no se pueden hacer inmutables simplemente usando la finalpalabra clave. finalsolo evita la reasignación.

final MyObject m = new MyObject (); //m es del tipo de referencia m . data = 100 ; // OK. Podemos cambiar el estado del objeto m (m es mutable y final no cambia este hecho) m = new MyObject (); // no compila. m es final, por lo que no se puede reasignar             

Los contenedores primitivos ( Integer, Long, Short, Double, Float, Character, Byte, Boolean) también son inmutables. Las clases inmutables se pueden implementar siguiendo algunas pautas simples. [13]

JavaScript

En JavaScript , todos los tipos primitivos (Undefined, Null, Boolean, Number, BigInt, String, Symbol) son inmutables, pero los objetos personalizados generalmente son mutables.

function doSomething ( x ) { /* ¿cambiar x aquí cambia el original? */ }; var str = 'a string' ; var obj = { an : 'object' }; doSomething ( str ); // las cadenas, los números y los tipos bool son inmutables, la función obtiene una copia doSomething ( obj ); // los objetos se pasan por referencia y son mutables dentro de la función doAnotherThing ( str , obj ); // `str` no ha cambiado, pero `obj` puede haberlo hecho.                 

Para simular la inmutabilidad de un objeto, se pueden definir propiedades como de sólo lectura (escribibles: falso).

var obj = {}; Object . defineProperty ( obj , 'foo' , { value : 'bar' , writable : false }); obj . foo = 'bar2' ; // ignorado silenciosamente             

Sin embargo, el método anterior permite agregar nuevas propiedades. Otra opción es usar Object.freeze para hacer que los objetos existentes sean inmutables.

var obj = { foo : 'bar' }; Object . freeze ( obj ); obj . foo = 'bars' ; // no se puede editar la propiedad, se ignora silenciosamente obj . foo2 = 'bar2' ; // no se puede agregar la propiedad, se ignora silenciosamente            

Con la implementación de ECMA262, JavaScript tiene la capacidad de crear referencias inmutables que no se pueden reasignar. Sin embargo, el uso de una constdeclaración no significa que el valor de la referencia de solo lectura sea inmutable, sino que el nombre no se puede asignar a un nuevo valor.

const SIEMPRE_INMUTABLE = verdadero ;   try { ALWAYS_IMMUTABLE = false ; } catch ( err ) { console.log ( "No se puede reasignar una referencia inmutable. " ) ; }        constante arr = [ 1 , 2 , 3 ]; arr . push ( 4 ); console . log ( arr ); // [1, 2, 3, 4]      

El uso de estados inmutables se ha convertido en una tendencia creciente en JavaScript desde la introducción de React , que favorece patrones de gestión de estados similares a Flux, como Redux . [14]

Perl

En Perl , se puede crear una clase inmutable con la biblioteca Moo simplemente declarando todos los atributos como de solo lectura:

paquete Inmutable ; usa Moo ;  tiene valor => ( es => 'ro' , # solo lectura predeterminado => 'data' , # se puede anular proporcionando al constructor # un valor: Immutable->new(value => 'something else'); );            1 ;

La creación de una clase inmutable solía requerir dos pasos: primero, crear accesores (automáticos o manuales) que impidieran la modificación de los atributos del objeto y, segundo, impedir la modificación directa de los datos de instancia de las instancias de esa clase (esto generalmente se almacenaba en una referencia hash y se podía bloquear con la función lock_hash de Hash::Util):

paquete Inmutable ; uso estricto ; uso advertencias ; uso base qw(Class::Accessor) ; # crear accesores de solo lectura __PACKAGE__ -> mk_ro_accessors ( qw(value) ); uso Hash::Util 'lock_hash' ;       sub new { my $class = shift ; return $class if ref ( $class ); die "Los argumentos para new deben ser pares clave => valor\n" a menos que ( @_ % 2 == 0 ); my %defaults = ( value => 'data' , ); my $obj = { %defaults , @_ , }; bless $obj , $class ; # evitar la modificación de los datos del objeto lock_hash %$obj ; } 1 ;                                       

O bien, con un accesor escrito manualmente:

paquete Inmutable ; uso estricto ; uso advertencias ; uso Hash::Util 'lock_hash' ;     sub new { my $class = shift ; return $class if ref ( $class ); die "Los argumentos para new deben ser pares clave => valor\n" a menos que ( @_ % 2 == 0 ); my %defaults = ( value => 'data' , ); my $obj = { %defaults , @_ , }; bless $obj , $class ; # evitar la modificación de los datos del objeto lock_hash %$obj ; }                                       # accesor de solo lectura sub valor { my $self = shift ; if ( my $new_value = shift ) { # intentando establecer un nuevo valor die "Este objeto no se puede modificar\n" ; } else { return $self -> { valor } } } 1 ;                     

Pitón

En Python , algunos tipos integrados (números, valores booleanos, cadenas, tuplas, conjuntos congelados) son inmutables, pero las clases personalizadas generalmente son mutables. Para simular la inmutabilidad en una clase, se podría anular la configuración y eliminación de atributos para generar excepciones:

clase  ImmutablePoint : """Una clase inmutable con dos atributos 'x' e 'y'."""  __ranuras__  =  [ 'x' ,  'y' ] def  __setattr__ ( self ,  * args ):  raise  TypeError ( "No se puede modificar la instancia inmutable." ) __delattr__  =  __setattr__ def  __init__ ( self ,  x ,  y ):  # Ya no podemos usar self.value = value para almacenar los datos de la instancia  , por lo que debemos llamar explícitamente a la superclase  super () .__ setattr__ ( 'x' ,  x )  super () .__ setattr__ ( 'y' ,  y )

Las colecciones de ayudantes de la biblioteca estándar, namestuple y typestuple, disponibles a partir de Python 3.6, crean clases inmutables simples. El siguiente ejemplo es aproximadamente equivalente al anterior, más algunas características similares a las de las tuplas:

desde  escribir  importar  NamedTuple importar  coleccionesPunto  =  colecciones .namedtuple ( 'Punto' , [ ' x' , 'y' ])  # lo siguiente crea una tupla con nombre similar a la clase  Point ( NamedTuple ) anterior:  x :  int  y :  int

Introducidas en Python 3.7, las clases de datos permiten a los desarrolladores emular la inmutabilidad con instancias congeladas. Si se crea una clase de datos congelada, dataclassesse anulará __setattr__()y __delattr__()se activará FrozenInstanceErrorsi se invoca.

desde  dataclasses  importar  dataclass@dataclass ( frozen = True ) clase  Punto :  x :  int  y :  int

Raqueta

Racket se diferencia sustancialmente de otras implementaciones de Scheme al hacer que su par de tipos principal ("cons cells") sea inmutable. En cambio, proporciona un par de tipos mutable paralelo, a través de mcons, mcar, set-mcar!etc. Además, se admiten muchos tipos inmutables, por ejemplo, cadenas y vectores inmutables, que se utilizan ampliamente. Las estructuras nuevas son inmutables de forma predeterminada, a menos que un campo se declare específicamente como mutable, o la estructura completa:

( struct foo1 ( x y )) ; todos los campos son inmutables ( struct foo2 ( x [ y #:mutable ])) ; un campo mutable ( struct foo3 ( x y ) #:mutable ) ; todos los campos son mutables              

El lenguaje también admite tablas hash inmutables, implementadas funcionalmente, y diccionarios inmutables.

Óxido

El sistema de propiedad de Rust permite a los desarrolladores declarar variables inmutables y pasar referencias inmutables. De forma predeterminada, todas las variables y referencias son inmutables. Las variables y referencias mutables se crean explícitamente con la mutpalabra clave.

Los elementos constantes en Rust son siempre inmutables.

// Los elementos constantes son siempre inmutables const ALWAYS_IMMUTABLE : bool = true ;   estructura  Objeto { x : usize , y : usize , }   fn  main () { // declara explícitamente una variable mutable let mut mutable_obj = Object { x : 1 , y : 2 }; mutable_obj . x = 3 ; // ok                deje que mutable_ref = & mut mutable_obj ; mutable_ref . x = 1 ; // ok         deje que inmutable_ref = & mutable_obj ; inmutable_ref . x = 3 ; // error E0594        // por defecto, las variables son inmutables let immutable_obj = Object { x : 4 , y : 5 }; immutable_obj . x = 6 ; // error E0596             deje que mutable_ref2 = & mut inmutable_obj ; // error E0596       deje que inmutable_ref2 = & inmutable_obj ; inmutable_ref2 . x = 6 ; // error E0594 }        

Escala

En Scala , cualquier entidad (en sentido estricto, un enlace) se puede definir como mutable o inmutable: en la declaración, se puede utilizar val(valor) para entidades inmutables y var(variable) para entidades mutables. Tenga en cuenta que, aunque un enlace inmutable no se puede reasignar, aún puede hacer referencia a un objeto mutable y aún es posible llamar a métodos de mutación en ese objeto: el enlace es inmutable, pero el objeto subyacente puede ser mutable.

Por ejemplo, el siguiente fragmento de código:

val maxValue = 100 var valorActual = 1      

define una entidad inmutable maxValue(el tipo entero se infiere en tiempo de compilación) y una entidad mutable denominada currentValue.

De manera predeterminada, las clases de colección como Listy Mapson inmutables, por lo que los métodos de actualización devuelven una nueva instancia en lugar de mutar una existente. Si bien esto puede parecer ineficiente, la implementación de estas clases y sus garantías de inmutabilidad significan que la nueva instancia puede reutilizar nodos existentes, lo que, especialmente en el caso de crear copias, es muy eficiente. [15] [ se necesita una mejor fuente ]

Véase también

Referencias

Este artículo contiene material del libro Patrones de diseño de Perl

  1. ^ "adjetivo inmutable - Definición, imágenes, pronunciación y notas de uso - Oxford Advanced Learner's Dictionary en OxfordLearnersDictionaries.com". www.oxfordlearnersdictionaries.com .
  2. ^ abc Goetz et al. Concurrencia en Java en la práctica . Addison Wesley Professional, 2006, Sección 3.4. Inmutabilidad
  3. ^ "6.005 — Construcción de software".
  4. ^ David O'Meara (abril de 2003). "Objetos mutables e inmutables: asegúrese de que los métodos no se puedan anular". Java Ranch . Consultado el 14 de mayo de 2012 . La forma preferida es hacer que la clase sea final. Esto a veces se conoce como "inmutabilidad fuerte". Evita que alguien extienda su clase y la haga mutable accidental o deliberadamente.
  5. ^ ab Bloch, Joshua (2018). "Effective Java: Programming Language Guide" (tercera edición). Addison-Wesley. ISBN 978-0134685991.
  6. ^ "Funciones integradas — Documentación de Python v3.0". docs.python.org .
  7. ^ Skeet, Jon (23 de marzo de 2019). C# en profundidad . Manning. ISBN 978-1617294532.
  8. ^ "Usar tipos de registros - Tutorial de C# - C#". learn.microsoft.com . 14 de noviembre de 2023 . Consultado el 23 de febrero de 2024 .
  9. ^ "Registros - Referencia de C# - C#". learn.microsoft.com . 25 de mayo de 2023 . Consultado el 23 de febrero de 2024 .
  10. ^ ab D Especificación del lenguaje § 18
  11. ^ D Especificación del lenguaje § 12.16 (Los términos matriz y porción se usan indistintamente).
  12. ^ "Cómo crear una clase y un objeto inmutables en Java: ejemplo de tutorial". Javarevisited.blogspot.co.uk. 2013-03-04 . Consultado el 2014-04-14 .
  13. ^ "Objetos inmutables". javapractices.com . Consultado el 15 de noviembre de 2012 .
  14. ^ "Inmutabilidad en JavaScript: una visión contraria". Desalasworks .
  15. ^ "Scala 2.8 Collections API – Clases de colecciones concretas e inmutables". Scala-lang.org . Consultado el 14 de abril de 2014 .

Enlaces externos