Welcome to Our Website

Shallow vs. Deep Copy en Java

en este artículo de mi Curso Gratuito de Java 8, discutiré la diferencia entre una copia profunda y una copia superficial. Puede descargar las diapositivas y el artículo en formato PDF aquí.

¿Qué Es una Copia?

para empezar, me gustaría destacar lo que es una copia en Java. Primero, vamos a diferenciar entre una copia de referencia y una copia de objeto. Una copia de referencia, como su nombre indica, crea una copia de una variable de referencia que apunta a un objeto., Si tenemos un objeto Car, con una variable myCar apuntando a él y hacemos una copia de referencia, ahora tendremos dos variables myCar, pero aún así un objeto.

Ejemplo 1

Una copia de objetos crea una copia del objeto en sí mismo. Así que si copiamos de nuevo nuestro objeto car, crearíamos una copia del objeto en sí, así como una segunda variable de referencia que hace referencia al objeto copiado.

Ejemplo 2

¿Qué Es un Objeto?,

tanto una copia profunda como una copia superficial son tipos de copias de objetos, pero ¿qué es realmente un objeto? A menudo, cuando hablamos de un objeto, hablamos de él como una sola unidad que no se puede descomponer más, como un humilde grano de café. Sin embargo, eso es demasiado simple.

Ejemplo 3

Digamos que tenemos un objeto de la Persona. Nuestro objeto persona está de hecho compuesto de otros objetos, como se puede ver en el Ejemplo 4. Nuestra persona contiene un objeto nombre y un objeto dirección., El nombre a su vez, contiene un objeto FirstName y un LastName; el objeto Address está compuesto por un objeto Street y un objeto City. Así que cuando hablo de persona en este artículo, en realidad Estoy hablando de toda esta red de objetos.

Ejemplo 4

Entonces, ¿por qué vamos a copiar esta Persona objeto? Una copia de objeto, normalmente llamada clon, se crea si queremos modificar o mover un objeto, conservando el objeto original. Hay muchas maneras diferentes de copiar un objeto que puedes aprender en otro artículo., En este artículo usaremos específicamente un constructor de copias para crear nuestras copias.

copia superficial

primero hablemos de la copia superficial. Una copia superficial de un objeto copia el objeto ‘principal’, pero no copia los objetos internos. Los ‘objetos internos’ se comparten entre el objeto original y su copia. Por ejemplo, en nuestro objeto Person, crearíamos una segunda persona, pero ambos objetos compartirían los mismos objetos Name y Address.

veamos un ejemplo de codificación. En el Ejemplo 5, Tenemos nuestra clase Person, que contiene un objeto Name and Address., El constructor copy toma el objeto originalPerson y copia sus variables de referencia.

Ejemplo 5

El problema con la copia superficial es que los dos objetos no son independientes. Si modifica el objeto Name de una persona, el cambio se reflejará en el objeto other Person.

Vamos a aplicar esto a un ejemplo. Digamos que tenemos un objeto persona con una variable de referencia madre; luego, hacemos una copia de madre, creando un objeto segunda persona, hijo. Si más adelante en el código, el hijo intenta moveOut () modificando su objeto de dirección, la madre se mueve con él!,

Person mother = new Person(new Name(…), new Address(…));Person son = new Person(mother);son.moveOut(new Street(…), new City(…));

ejemplo 6

esto ocurre porque nuestros objetos madre e hijo comparten el mismo objeto de dirección, como se puede ver ilustrado en el Ejemplo 7. Cuando cambiamos la dirección en un objeto, cambia en ambos!

Ejemplo 7

copia profunda

a diferencia de la copia superficial, una copia profunda es una copia totalmente independiente de un objeto. Si copiamos nuestro objeto Person, copiaríamos toda la estructura del objeto.,

ejemplo 8

un cambio en el objeto Address de una persona no se reflejaría en el otro objeto como puede ver en el diagrama del Ejemplo 8. Si echamos un vistazo al código en el ejemplo 9, puede ver que no solo estamos usando un constructor de copia en nuestro objeto Person, sino que también estamos utilizando constructores de copia en los objetos internos.

ejemplo 9

Usando esta copia profunda, podemos reintentar el ejemplo madre-hijo del Ejemplo 6. ¡Ahora el hijo es capaz de mudarse con éxito!,

sin embargo, ese no es el final de la historia. Para crear una verdadera copia profunda, necesitamos seguir copiando todos los elementos anidados del objeto Person, hasta que solo queden tipos primitivos e «inmutables». Veamos la clase Street para ilustrar mejor esto:

ejemplo 10

El objeto Street se compone de dos variables de instancia: String name y int number. el número int es un valor primitivo y no un objeto. Es solo un valor simple que no se puede compartir, por lo que al crear una variable de segunda instancia, estamos creando automáticamente una copia independiente., String es una cadena inmutable. En resumen, un inmutable es un objeto que, una vez creado, nunca puede ser cambiado de nuevo. Por lo tanto, puede compartirlo sin tener que crear una copia profunda de él.

conclusión

Para concluir, me gustaría hablar sobre algunas técnicas de codificación que utilizamos en nuestro ejemplo madre-hijo. El hecho de que una copia profunda le permita cambiar los detalles internos de un objeto, como el objeto Address, no significa que deba hacerlo., Hacerlo disminuiría la calidad del código, ya que haría que la clase Person sea más frágil a los cambios – cada vez que se cambie la clase Address, tendrá que (potencialmente) aplicar cambios a la clase Person también. Por ejemplo, si la clase Address ya no contiene un objeto Street, tendríamos que cambiar el método moveOut() en la clase Person por encima de los cambios que ya hicimos en la clase Address.

en el Ejemplo 6 de este artículo solo elegí usar un nuevo objeto Street and City para ilustrar mejor la diferencia entre una copia superficial y una profunda., En su lugar, le recomendaría que asigne un nuevo objeto de dirección, convirtiendo efectivamente a un híbrido de una copia superficial y una profunda, como puede ver en el ejemplo 10:

Person mother = new Person(new Name(…), new Address(…));Person son = new Person(mother);son.moveOut(new Address(...));

ejemplo 11

en términos orientados a objetos, esto viola la encapsulación, y por lo tanto debe evitarse. La encapsulación es uno de los aspectos más importantes de la programación orientada a objetos. En este caso, había violado la encapsulación al acceder a los detalles internos del objeto Address en nuestra clase Person., Esto daña nuestro código porque ahora hemos enredado a la clase Person en la clase Address y si hacemos cambios en la clase Address en el futuro, podría dañar a la clase Person como he explicado anteriormente. Si bien es obvio que necesita interconectar sus diversas clases para tener un proyecto de codificación, cada vez que conecta dos clases, necesita analizar los costos y beneficios.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *