Soy nuevo en la programación orientada a objetos, y un concepto que me ha llevado un tiempo comprender es la inmutabilidad. Creo que la bombilla se apagó anoche pero quiero verificar:
Cuando me encuentro con afirmaciones de que un objeto inmutable no se puede cambiar, estoy perplejo porque, por ejemplo, puedo hacer lo siguiente:
NSString *myName = @"Bob";
myName = @"Mike";
Allí, acabo de cambiar myName, de tipo inmutable NSString. Mi problema es que la palabra "objeto" puede referirse al objeto físico en la memoria, o la abstracción, "myName". La primera definición se aplica al concepto de inmutabilidad.
En cuanto a la variable, una definición más clara (para mí) de inmutabilidad es que el valor de un objeto inmutable solo puede cambiarse cambiando también su ubicación en la memoria, es decir, su referencia (también conocida como su puntero).
¿Es correcto o todavía estoy perdido en el bosque?
fuente
NSString
, es un " puntero a yNSString
", que no es inmutable. No sé nada de objetivo C, pero supongo en su ejemplo que@"Mike"
es la creación de una nueva instancia deNSString
y asignarlo al puntero ,myName
. Por lo tanto, no ha cambiado el objeto al quemyName
apuntaba, solo a lo que apuntaba.Respuestas:
Parece que te diriges en la dirección correcta, pero aún no lo entiendo. Esto está mal:
En su fragmento de código,
myName
no es de tipo inmutableNSString
, es de tipo mutableNSString*
(puntero a NSString). Parece que la clave que falta es entender que un puntero es solo otro valor , y tiene una vida completamente separada de lo que señala (o cosas, si lo cambia a mitad de su vida útil).Tu dices:
Esto está mal. Un objeto no posee los punteros que apuntan a él, ni la ubicación de la memoria de un objeto está controlada ni afectada por ningún puntero.
Entonces, los dos
NSString
objetos en su ejemplo (@"Bob"
y@"Mike"
) están completamente separados de lamyName
variable. También están completamente separados el uno del otro. Cuando cambiamyName
para señalar en@"Mike"
lugar de señalar@"Bob"
, no está cambiando losNSString
objetos.Para completar, notaré que los recolectores de basura hacen que esto sea más complejo ya que los cambios en los punteros pueden afectar los objetos a los que apuntan (ed). Sin embargo, este es un detalle de implementación que no debería afectar el comportamiento observable del código.
fuente
Estás perdido en las palabras. La inmutabilidad significa: siempre que no cambie la variable, siempre "contendrá" el mismo valor, sin importar lo que haga con otras variables.
Contraejemplo en C (un poco simplificado, suponiendo una arquitectura que lo permita):
Ahora ya no "contiene" (es decir, apunta a) la cadena "Hello World", sino que es "Yello World".
En lenguajes donde las cadenas son inmutables, como Java y (EDITAR: seguro) C #, no puede hacer eso. De ninguna manera. Esto significa que cada parte del programa puede mantener de forma segura una referencia a la cadena y confiar en que su contenido nunca cambie; de lo contrario, tendrían que crear una copia solo para estar seguros.
Pero la variable aún es mutable. Puede dejar que apunte a otro objeto. Es solo que el objeto en sí no cambiará a sus espaldas.
fuente
unsafe
código.Estás confundiendo variables con objetos. Las variables se pueden usar para almacenar referencias a objetos, pero NO son objetos. Los objetos son inmutables, no variables, por lo que puede cambiar la variable de un objeto a otro, pero no puede cambiar los atributos del objeto si es inmutable.
Piense en el objeto como un vecino ruidoso y borracho. Si él es razonable (mutable), puede llamar a su puerta y convertirlo a un estilo de vida donde no haga tanto ruido. Pero si él es inmutable, ¡tu único cambio es esperar que alguien más se mude!
fuente
Una variable no es un objeto. Una variable es un nombre, que se refiere a un objeto (o más generalmente a un valor).
Por ejemplo, "el portero" es un nombre que usamos para referirnos al objeto (persona) responsable de defender el objetivo. Pero si sustituyo a esa persona por otra (porque la primera está lesionada o no), la nueva persona ahora se conoce como el "portero".
La declaración de asignación es lo que hace que las variables sean mutables (algunos lenguajes, como Haskell, no lo tienen y, de hecho, usan variables inmutables). Le permite redefinir el significado de un nombre y así reasignar el valor.
Ahora los objetos mismos pueden ser inmutables. Hace unos miles de años, uno podría haber pensado que los diamantes eran inmutables. No importa lo que hiciste con un diamante, no puedes modificarlo. Ya sea que lo llames waggawooga (se traduce libremente como "la piedra brillante más grande de nuestra tribu") o dejaste de llamarlo así (porque encontraste una más grande), el diamante se mantuvo igual. En contraste, el trozo de madera que solías tallar en imágenes divertidas con tu waggawooga no permaneció igual. Resultó mutable. Incluso si tuviera el mismo nombre todo el tiempo.
Tanto las variables como los valores pueden ser inmutables (independientemente). En este caso, son los objetos los que son inmutables. Una vez que construye un
NSString
, no puede modificarlo. Puedes llamarlo por nombres y pasarlo, pero seguirá igual. En contraste con eso,NSMutableString
se puede cambiar después de la creación, por ejemplo, llamando alsetString
método.fuente
Creo que te sientes perdido, porque estás mezclando dos conceptos: el objeto mismo y el nombre de la variable vinculada a ese objeto.
Los objetos inmutables no se pueden cambiar. Período. Sin embargo, el nombre de la variable (símbolo) vinculado a un objeto inmutable puede modificarse para vincularse a otro objeto inmutable.
En otras palabras, lo que hiciste en estas dos líneas fue:
myName
a ese objetomyName
a ese objetofuente
Su tipo no es un
NSString
, es un " puntero a unNSString
", que no es inmutable. No sé nada del objetivo C, pero supongo en su ejemplo que@"Mike"
está creando una nueva instanciaNSString
y asignándola al punteromyName
. Por lo que no ha cambiado el objeto quemyName
estaba apuntando a, justo lo que estaba señalando.fuente
Aquí hay un ejemplo de un objeto mutable: una matriz de
char
en C:Puedo cambiar el contenido de
str
mi corazón (siempre que no sea más de 10 caracteres). Para que sea reconocido como una cadena por las funciones de la biblioteca de cadenas C, debe haber un 0 al final, para que pueda contener cadenas de hasta 9 caracteres de longitud:und so weiter .
Contraste esto con un objeto de cadena en Java:
La instancia de cadena (el fragmento de memoria que contiene los caracteres 'H', 'e', 'l', 'l' y 'o') no se puede modificar; No puedo alterar ninguno de los contenidos de esa cadena. Cuando escribes algo como
no está agregando "Mundo" al final de la instancia de "Hola"; está creando una nueva instancia , copiando "Hello World" y actualizando
foo
para referirse a esa nueva instancia de cadena.foo
no contiene en sí la instancia de cadena; solo se refiere a esa instancia (similar a un puntero en C u Obj-C), de ahí que los tipos como String se denominen tipos de referencia.fuente