Es un punto crucial, pero en mi humilde opinión vale la pena entenderlo.
Todos los lenguajes OO siempre hacen copias de referencias, y nunca copian un objeto 'invisiblemente'. Sería mucho más difícil escribir programas si los lenguajes OO funcionaran de otra manera. Por ejemplo, funciones y métodos, nunca podrían actualizar un objeto. Java, y la mayoría de los lenguajes OO serían casi imposibles de usar sin una complejidad adicional significativa.
Se supone que un objeto en un programa tiene algún significado. Por ejemplo, representa algo específico en el mundo físico real. Por lo general, tiene sentido tener muchas referencias a lo mismo. Por ejemplo, la dirección de mi casa se puede dar a muchas personas y organizaciones, y esa dirección siempre se refiere a la misma ubicación física. Entonces, el primer punto es que los objetos a menudo representan algo que es específico, real o concreto; y así poder tener muchas referencias a lo mismo es extremadamente útil. De lo contrario, sería más difícil escribir programas.
Cada vez que pasa a
como argumento / parámetro a otra función, por ejemplo, llamando
foo(Dog aDoggy);
o aplicando un método a
, el código del programa subyacente hace una copia de la referencia, para producir una segunda referencia al mismo objeto.
Además, si el código con una referencia copiada está en un hilo diferente, entonces ambos pueden usarse simultáneamente para acceder al mismo objeto.
Entonces, en la mayoría de los programas útiles, habrá múltiples referencias al mismo objeto, porque esa es la semántica de la mayoría de los lenguajes de programación OO.
Ahora, si lo pensamos bien, dado que pasar por referencia es el único mecanismo disponible en muchos lenguajes OO (C ++ admite ambos), podríamos esperar que sea el comportamiento predeterminado 'correcto' .
En mi humilde opinión, el uso de referencias es el valor predeterminado correcto , por un par de razones:
- Garantiza que el valor de un objeto utilizado en dos lugares diferentes es el mismo. Imagine colocar un objeto en dos estructuras de datos diferentes (matrices, listas, etc.) y realizar algunas operaciones en un objeto que lo cambia. Eso podría ser una pesadilla para depurar. Más importante aún, es el mismo objeto en ambas estructuras de datos, o el programa tiene un error.
- Puede refactorizar felizmente el código en varias funciones, o fusionar el código de varias funciones en una sola, y la semántica no cambia. Si el lenguaje no proporcionara semántica de referencia, sería aún más complejo modificar el código.
También hay un argumento de eficiencia; hacer copias de objetos completos es menos eficiente que copiar una referencia. Sin embargo, creo que se pierde el punto. Las referencias múltiples al mismo objeto tienen más sentido y son más fáciles de usar, ya que coinciden con la semántica del mundo físico real.
Entonces, en mi humilde opinión, generalmente tiene sentido tener múltiples referencias al mismo objeto. En los casos inusuales en los que eso no tiene sentido en el contexto de un algoritmo, la mayoría de los idiomas proporcionan la capacidad de hacer un 'clon' o copia profunda. Sin embargo, ese no es el valor predeterminado.
Creo que las personas que argumentan que este no debería ser el predeterminado están utilizando un lenguaje que no proporciona recolección de basura automática. Por ejemplo, anticuado C ++. El problema es que necesitan encontrar una manera de recolectar objetos 'muertos' y no reclamar objetos que aún pueden ser necesarios; tener múltiples referencias al mismo objeto lo hace difícil.
Creo que si C ++ tuvo una recolección de basura de costo suficientemente bajo, de modo que todos los objetos a los que se hace referencia son recolección de basura, entonces gran parte de la objeción desaparece. Todavía habrá algunos casos en los que la semántica de referencia no es lo que se necesita. Sin embargo, en mi experiencia, las personas que pueden identificar esas situaciones también suelen ser capaces de elegir la semántica adecuada de todos modos.
Creo que hay alguna evidencia de que una gran cantidad de código en un programa C ++ está ahí para manejar o mitigar la recolección de basura. Sin embargo, escribir y mantener ese tipo de código 'infraestructural' agrega costos; está ahí para hacer que el lenguaje sea más fácil de usar o más robusto. Entonces, por ejemplo, el lenguaje Go está diseñado con un enfoque en remediar algunas de las debilidades de C ++, y no tiene otra opción que la recolección de basura.
Por supuesto, esto es irrelevante en el contexto de Java. También fue diseñado para ser fácil de usar, y también lo ha sido la recolección de basura. Por lo tanto, tener múltiples referencias es la semántica predeterminada, y es relativamente seguro en el sentido de que los objetos no se reclaman mientras haya una referencia a ellos. Por supuesto, una estructura de datos podría retenerlos porque el programa no se ordena correctamente cuando realmente ha terminado con un objeto.
Entonces, volviendo a su pregunta (con un poco de generalización), ¿cuándo querría más de una referencia al mismo objeto? Prácticamente en cada situación que se me ocurre. Son la semántica predeterminada del mecanismo de paso de parámetros de la mayoría de los idiomas. Sugiero que se debe a que la semántica predeterminada de manejar objetos que existe en el mundo real tiene que ser básicamente por referencia (porque los objetos reales están ahí fuera).
Cualquier otra semántica sería más difícil de manejar.
Dog a = new Dog("rover"); // initialise with name
DogList dl = new DogList()
dl.add(a)
...
a.setOwner("Mr Been")
Sugiero que el "rover" en dl
debería ser el afectado setOwner
o los programas se volverán difíciles de escribir, comprender, depurar o modificar. Creo que la mayoría de los programadores estarían perplejos o consternados de lo contrario.
luego se vende el perro:
soldDog = dl.lookupOwner("rover", "Mr Been")
soldDog.setOwner("Mr Mcgoo")
Este tipo de procesamiento es común y normal. Por lo tanto, la semántica de referencia es la predeterminada porque generalmente tiene más sentido.
Resumen: siempre tiene sentido tener múltiples referencias al mismo objeto.