2009-05-26 12 views
8

Me pregunto cómo se define la inmutabilidad? Si los valores no están expuestos como públicos, entonces no se pueden modificar, ¿es suficiente?La verdadera definición de inmutabilidad?

¿Se pueden modificar los valores dentro del tipo, no por el cliente del tipo?

¿O solo se puede establecer dentro de un constructor? Si es así, en los casos de doble inicialización (usando la palabra clave this en estructuras, etc.) ¿sigue siendo válido para tipos inmutables?

¿Cómo puedo garantizar que el tipo es 100% inmutable?

Respuesta

23

Si los valores no se muestran como públicos, entonces no se pueden modificar, ¿es suficiente?

No, porque necesita acceso de lectura.

¿Se pueden modificar los valores dentro del tipo, no por el cliente del tipo?

No, porque eso sigue siendo una mutación.

¿O solo se puede establecer dentro de un constructor?

Ding ding ding! Con el punto adicional de que los tipos inmutables a menudo tienen métodos que construyen y devuelven nuevas instancias, y también a menudo tienen constructores adicionales marcados como internal específicamente para el uso de esos métodos.

¿Cómo puedo garantizar que el tipo es 100% inmutable?

En .Net es difícil obtener una garantía como esta, porque puede usar la reflexión para modificar (mutar) miembros privados.

+2

Casi cubre todo ;-p –

+0

Hola Marc, estoy sorprendido de no verte en mis recientes preguntas inmutables. La inmutabilidad me recuerda a ti :) –

3

Aquí es la definición de la inmutabilidad de Wikipedia (link)

"En orientada a objetos y la programación funcional, un objeto inmutable es un objeto cuyo estado no puede ser modificado después de su creación."

Esencialmente, una vez que se crea el objeto, ninguna de sus propiedades se puede cambiar. Un ejemplo es la clase String. Una vez que se crea un objeto String, no se puede cambiar. Cualquier operación realizada en realidad crea un nuevo objeto String.

1

He aprendido que la inmutabilidad es cuando configura todo en el constructor y no puede modificarlo más adelante durante la vida del objeto.

1

La definición de inmutabilidad se puede encontrar en Google.

Ejemplo:

inmutable - literalmente, no es capaz de cambiar.
www.filosofia.net/materiales/rec/glosaen.htm

En términos de estructuras de datos inmutables, la definición típica es write-once-read-many, en otras palabras, como dices, una vez creada, no se puede cambiar.

Hay algunos casos que se encuentran ligeramente en el área gris. Por ejemplo, las cadenas .NET se consideran inmutables, porque no pueden cambiar, sin embargo, StringBuilder modifica internamente un objeto String.

1

Una inmutabilidad es esencialmente una clase que se fuerza a ser definitiva desde su propio código. Una vez que está allí, nada se puede cambiar. En mi conocimiento, las cosas están establecidas en el constructor y eso es todo. No veo cómo algo podría ser inmutable de lo contrario.

3

Muchas preguntas allí. Voy a tratar de responder a cada uno de ellos individualmente:

  • "Me pregunto cómo se define la inmutabilidad?" - Directamente desde el Wikipedia page (y una definición muy exactos/concisa)

    Un objeto inmutable es un objeto cuyo estado no puede ser modificado después de su creación

  • "Si los valores no están expuestos como público, entonces no se puede modificar, ¿es suficiente? " - No del todo. No se puede modificar en de ninguna manera, por lo que debe asegurarse de que los métodos/funciones no cambien el estado del objeto, y si realiza operaciones, siempre devuelva una nueva instancia.

  • "¿Se pueden modificar los valores dentro del tipo, no por el cliente del tipo?" - Técnicamente, no puede ser modificado ni por dentro ni por un consumidor del tipo. En la práctica, existen tipos como System.String (un tipo de referencia para la materia) que pueden considerarse mutables para casi todos los propósitos prácticos, aunque no en teoría.

  • "¿O solo se pueden establecer dentro de un constructor?" - Sí, en teoría ese es el único lugar donde se puede establecer el estado (variables).

  • "Si es así, en los casos de doble inicialización (utilizando la palabra clave this en structs, etc.) ¿sigue siendo válido para tipos inmutables?" - Sí, eso está perfectamente bien, porque es parte del proceso de inicialización (creación) y la instancia no se devuelve hasta que haya finalizado.

  • "¿Cómo puedo garantizar que el tipo es 100% inmutable?" - Las siguientes condiciones deben asegurar eso. (Alguien por favor señale si me falta uno.)

    1. No exponga ninguna variable. Todos deben mantenerse private (ni siquiera protected es aceptable, ya que las clases derivadas pueden modificar el estado).
    2. No permita que ningún método de instancia modifique el estado (variables). Esto solo debe hacerse en el constructor, mientras que los métodos deben crear nuevas instancias usando un constructor particular si requieren devolver un objeto "modificado".
    3. Todos los miembros que están expuestos (como de solo lectura) u objetos devueltos por los métodos deben ser ellos mismos ser inmutables.

    Nota: no se puede asegurar la inmutabilidad de los tipos derivados, ya que pueden definir nuevas variables. Esta es una razón para marcar cualquier tipo que desee para asegurarse de que sea inmutable como sealed, de modo que ninguna clase derivada pueda considerarse de su tipo base inmutable en ningún lugar del código.

Espero que ayude.

+1

Yo agregaría que, si expones a los miembros, probablemente también deberían ser inmutables ... –

+0

@Denis: Sí, sabía que me había perdido algo obvio. ¡Gracias! – Noldorin

+0

Gracias. ¿Qué pasa si alguien envuelve mi clase inmutable para hacer un tipo inmutable? ¿Quiere decir que expone el punto.X, apunte.Y para leer y los usa para reflejar/actualizar los cambios? Alguien me dijo que la gente incluso pasa por alto las clases selladas. –

7

Los carteles anteriores ya han establecido que debe asignar valores a sus campos en el constructor y luego mantener sus manos alejadas de ellos. Pero a veces es más fácil decirlo que hacerlo. Digamos que su objeto inmutable expone una propiedad del tipo List<string>. ¿Se permite que esa lista cambie? Y si no, ¿cómo lo controlarás?

Eric Lippert ha escrito una serie de publicaciones en su blog sobre la inmutabilidad en C# que pueden resultarle interesantes: you find the first part here.

+0

Esa es una pregunta interesante. ¿Puedes hacer la lista de solo lectura? –

+4

Eso depende de qué tipo exponer. Con una lista no puede, pero si expone un ReadOnlyCollection es posible que (no sé lo suficiente al respecto para afirmar que se garantiza que es de solo lectura). Pero también los arreglos regulares son mutables, por lo que realmente necesita prestar atención a los tipos que expone en un tipo inmutable. –

+0

+1 para vincular al Sr. Lippert: P – Lucas

5

Una cosa que creo que se puede perder en todas estas respuestas es que creo que un objeto puede considerarse inmutable incluso si su estado interno cambia, siempre y cuando esos cambios internos no sean visibles para el código 'cliente'.

Por ejemplo, la clase System.String es inmutable, pero creo que se permite cachear el código hash para una instancia, por lo que el hash solo se calcula en la primera llamada al GetHashCode(). Tenga en cuenta que, hasta donde yo sé, la clase System.String hace no hacer esto, pero creo que podría y aún se puede considerar inmutable. Por supuesto, cualquiera de estos cambios debería manejarse de manera segura (de acuerdo con el aspecto no observable de los cambios).

Para ser sincero, no puedo pensar en muchas razones por las que uno podría querer o necesitar este tipo de 'mutabilidad invisible'.

+0

Buen punto Michael. –

+2

Un ejemplo: splay trees. La mutación interna se usa puramente para mejorar el rendimiento de la búsqueda, pero el código del cliente no puede detectar que se ha producido una mutación (por supuesto, también es posible la implementación mutable de árboles splay). –

+0

Compare la palabra clave C++ "mutable", que designa un miembro de la clase eso se puede cambiar incluso en una operación const. Por lo general, esto se debe a motivos de rendimiento, lo que respalda la evaluación diferida de algo u otro. –

1

Desafortunadamente no hay palabras clave inmutables en C#/vb.net, aunque se ha debatido, pero si no hay autopropiedades y todos los campos se declaran con el modificador readonly (campos de solo lectura se pueden apostar en el constructor) y todos campos está declarado de un tipo inmutable habrá asegurado su auto inmutabilidad.

1

Un objeto inmutable es aquel cuyo estado observable nunca puede ser modificado por ninguna secuencia plausible de ejecución de código. Un tipo inmutable es aquel que garantiza que cualquier instancia expuesta al mundo exterior será inmutable (este requisito a menudo se establece como que requiere que el estado del objeto solo se establezca en su constructor, esto no es estrictamente necesario en el caso de objetos con constructores privados, ni es suficiente en el caso de objetos que invocan métodos externos sobre ellos mismos durante la construcción).

Un punto que otras respuestas han descuidado, sin embargo, es una definición del estado de un objeto. Si Foo es una clase, el estado de un List<Foo> consiste en la secuencia de identidades de objeto contenidas en el mismo. Si la única referencia a una instancia particular de List<Foo> es mantenida por un código que no causará que esa secuencia cambie, ni la exponga al código que podría hacerlo, entonces esa instancia será inmutable, independientemente de si los objetos Foo a los que se hace referencia son mutable o inmutable.

Para utilizar una analogía, si se tiene una lista de VIN de automóvil (números de identificación del vehículo) impresos en papel a prueba de falsificaciones, la lista en sí misma sería inmutable aunque los automóviles no lo sean.Incluso si la lista contiene diez autos rojos hoy, podría contener diez autos azules mañana; aún serían, sin embargo, los mismos diez automóviles.

Cuestiones relacionadas