Conseguir mi cabeza alrededor de la inmutabilidad

12

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 declaraciones de que un objeto inmutable no se puede cambiar, estoy confundido porque puedo, por ejemplo, hacer lo siguiente:

NSString *myName = @"Bob";
myName = @"Mike";

Allí, acabo de cambiar miNombre, de tipo NSString inmutable. Mi problema es que la palabra "objeto" puede referirse al objeto físico en la memoria, o la abstracción, "miNombre". 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 conocido como su puntero).

¿Esto es correcto o aún estoy perdido en el bosque?

    
pregunta Michael Mangold 29.06.2011 - 14:25

7 respuestas

4

Parece que vas en la dirección correcta, pero aún no lo has conseguido. Esto es incorrecto:

  

Allí, acabo de cambiar miNombre, de tipo NSString inmutable. Mi problema es que la palabra "objeto" puede referirse al objeto físico en la memoria, o la abstracción, "miNombre".

En su fragmento de código, myName no es de tipo inmutable NSString , es de tipo mutable NSString* (puntero a NSString). Parece que lo que falta es comprender que un puntero es solo otro valor , y tiene una vida completamente diferente a la que señala (o cosas, si lo cambias en parte a lo largo de su vida útil).

Usted dice:

  

... 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).

Esto está mal. Un objeto no posee los punteros que lo apuntan, ni la ubicación de la memoria de un objeto se controla ni se ve afectada por ningún otro puntero hacia él.

Entonces, los dos objetos NSString en tu ejemplo ( @"Bob" y @"Mike" ) están completamente separados de la variable myName . También están completamente separados unos de otros. Cuando cambia myName para señalar a @"Mike" en lugar de señalar a @"Bob" , no está cambiando los objetos NSString .

Para completar, observare que los recolectores de basura hacen que esto sea más complejo, ya que los cambios en los indicadores 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.

    
respondido por el John Bartholomew 29.06.2011 - 15:05
17

Estás perdido en las palabras. Medios de inmutabilidad: mientras no cambies la variable, siempre "contendrá" el mismo valor, sin importar lo que hagas con otras variables.

Contraejemplo en C (un poco simplificado, asumiendo una arquitectura que lo permita):

 char *a = "Hello World";
 char *b = a;
 b[0] = 'Y';

Ahora ya no "contiene" (es decir, apunta a) la cadena "Hola mundo", pero en su lugar es "Mundo Yello".

En idiomas donde las cadenas son inmutables, como Java y (EDIT: safe) C #, no puedes 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 cambia; de lo contrario, tendrían que crear una copia para estar seguros.

Pero la variable todavía es mutable. Puedes dejar que apunte a otro objeto. Es solo que el objeto en sí no cambiará a tus espaldas.

    
respondido por el user281377 29.06.2011 - 14:33
10

Estás confundiendo variables con objetos. Las variables se pueden usar para almacenar referencias a objetos, pero NO son objetos. Se trata de objetos que son inmutables, no de 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 borracho y ruidoso. Si es razonable (mutable), puede que llames a su puerta y lo conviertas en 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!

    
respondido por el Kilian Foth 29.06.2011 - 14:58
6

Una variable no es un objeto. Una variable es un nombre, que se refiere a un objeto (o más generalmente 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 lo que sea), ahora se hace referencia a la nueva persona como el "portero".

La declaración de asignación es lo que hace que las variables sean mutables (algunos idiomas, como Haskell no lo tienen y de hecho utilizan variables inmutables). Le permite redefinir el significado de un nombre y, por lo tanto, reasignar el valor.

Ahora los objetos en sí mismos pueden ser inmutables. Hace unos pocos miles de años, uno podría pensar que los diamantes son inmutables. No importa lo que hiciste con un diamante, no pudiste modificarlo. Ya sea que lo hayas llamado waggawooga (que se traduce libremente como "la piedra brillante más grande de nuestra tribu") o que dejaste de llamarlo así (porque encontraste una más grande), el diamante siguió siendo el mismo. En contraste, la pieza de madera que solía tallar en fotos divertidas con su waggawooga no se mantuvo igual. Resultó ser 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 construyas un NSString , no puedes modificarlo. Puedes llamarlo por sus nombres y pasarlo, pero seguirá siendo el mismo. En contraste, NSMutableString se puede cambiar después de la creación, por ejemplo, llamando al método setString .

    
respondido por el back2dos 29.06.2011 - 15:02
4

Creo que te sientes perdido, porque estás mezclando dos conceptos: el objeto en sí y el nombre de la variable vinculado 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, se puede modificar para vincularse a otro objeto inmutable.

En otras palabras, lo que hiciste en estas dos líneas fue:

  1. crear un objeto de cadena inmutable con valor "Bob"
  2. vincular el símbolo myName a ese objeto
  3. crear un objeto de cadena inmutable con el valor "Mike"
  4. vincular el símbolo myName a ese objeto
respondido por el vartec 29.06.2011 - 14:55
2

Su tipo no es un NSString , es un " puntero a un NSString ", que no es inmutable. No sé nada del objetivo C, pero supongo que en su ejemplo, @"Mike" está creando una nueva instancia de NSString y asignándola al puntero myName . Así que no has cambiado el objeto al que myName estaba apuntando a, solo a lo que estaba apuntando.

    
respondido por el fwgx 29.06.2011 - 21:52
0

Aquí hay un ejemplo de un objeto mutable: una matriz de char en C:

char str[10];

Puedo cambiar el contenido de str al contenido de mi corazón (siempre y cuando no tenga más de 10 caracteres). Para que sea reconocida como una cadena por las funciones de la biblioteca de cadenas en C, tiene que haber un 0 al final, por lo que puede contener cadenas de hasta 9 caracteres de longitud:

strcpy(str, "hello"); // str now contains the string "hello
String foo = "Hello";
" strcpy(str, "world"); // str now contains the string "world
foo = foo + " World";
" str[0] = 'W'; // str now contains "World
char str[10];
"

und weiter .

Contrasta esto con un objeto de cadena en Java:

strcpy(str, "hello"); // str now contains the string "hello
String foo = "Hello";
" strcpy(str, "world"); // str now contains the string "world
foo = foo + " World";
" str[0] = 'W'; // str now contains "World%pre%"

La cadena instancia (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

%pre%

no estás agregando "Mundo" al final de la instancia "Hola"; está creando una nueva instancia , copiando "Hello World" en ella y actualizando foo para referirse a esa nueva instancia de cadena.

foo no contiene la instancia de cadena; solo se refiere a esa instancia (similar a un puntero en C u Obj-C), por lo tanto, los tipos como String se denominan tipos de referencia.

    
respondido por el John Bode 29.06.2011 - 18:30

Lea otras preguntas en las etiquetas