18 - Referencia y clonación de objetos.


Hay que tener en cuenta que un objeto es una estructura de datos compleja. Luego cuando asignamos una variable de tipo objeto a otra variable lo que estamos haciendo es guardar la referencia del objeto. No se está creando un nuevo objeto, sino otra variable por la que podemos acceder al mismo objeto.

Si queremos crear un nuevo objeto idéntico a otro debemos utilizar el operador clone.

El siguiente ejemplo muestra la diferencia entre asignación y clonación:

<html>
<head>
<title>Pruebas</title>
</head>
<body>
<?php
class Persona {
  private $nombre;
  private $edad;
  public function fijarNombreEdad($nom,$ed)
  {
    $this->nombre=$nom;
    $this->edad=$ed;
  }
  public function retornarNombre()
  {
    return $this->nombre;
  }
  public function retornarEdad()
  {
    return $this->edad;
  }
}

$persona1=new Persona();
$persona1->fijarNombreEdad('Juan',20);
$x=$persona1;
echo 'Datos de la persona ($persona1):';
echo $persona1->retornarNombre().' - '.$persona1->retornarEdad().'<br>';
echo 'Datos de la persona ($x):';
echo $persona1->retornarNombre().' - '.$persona1->retornarEdad().'<br>';
$x->fijarNombreEdad('Ana',25);
echo 'Después de modificar los datos<br>';
echo 'Datos de la persona ($persona1):';
echo $persona1->retornarNombre().' - '.$persona1->retornarEdad().'<br>';
echo 'Datos de la persona ($x):';
echo $persona1->retornarNombre().' - '.$persona1->retornarEdad().'<br>';
$persona2=clone($persona1);
$persona1->fijarNombreEdad('Luis',50);
echo 'Después de modificar los datos de persona1<br>';
echo 'Datos de la persona ($persona1):';
echo $persona1->retornarNombre().' - '.$persona1->retornarEdad().'<br>';
echo 'Datos de la persona ($persona2):';
echo $persona2->retornarNombre().' - '.$persona2->retornarEdad().'<br>';
?>
</body>
</html>

Primero creamos un objeto de la clase Persona y cargamos su nombre y edad:

$persona1=new Persona();
$persona1->fijarNombreEdad('Juan',20);

Definimos una segunda variable $x y guardamos la referencia de la variable $persona1:

$x=$persona1;

Ahora imprimimos el nombre y edad de la persona accediéndolo primero por la variable $persona1 y luego por la variable $x (Se muestran los mismos datos porque en realidad estamos imprimiendo los atributos del mismo objeto):

 
echo 'Datos de la persona ($persona1):';
echo $persona1->retornarNombre().' - '.$persona1->retornarEdad().'<br>';
echo 'Datos de la persona ($x):';
echo $persona1->retornarNombre().' - '.$persona1->retornarEdad().'<br>';

Si modificamos el nombre y la edad de la persona llamando al método fijarNombreEdad mediante la variable $x:

$x->fijarNombreEdad('Ana',25);

luego imprimimos los atributos mediante las referencias al mismo objeto:

echo 'Después de modificar los datos<br>';
echo 'Datos de la persona ($persona1):';
echo $persona1->retornarNombre().' - '.$persona1->retornarEdad().'<br>';
echo 'Datos de la persona ($x):';
echo $persona1->retornarNombre().' - '.$persona1->retornarEdad().'<br>';

Para crear un segundo objeto y clonarlo del objeto referenciado por $persona1:

$persona2=clone($persona1);

Ahora cambiamos los atributos del primer objeto creado:

$persona1->fijarNombreEdad('Luis',50);

Luego imprimimos los atributos de los dos objetos:

echo 'Después de modificar los datos de persona1<br>';
echo 'Datos de la persona ($persona1):';
echo $persona1->retornarNombre().' - '.$persona1->retornarEdad().'<br>';
echo 'Datos de la persona ($persona2):';
echo $persona2->retornarNombre().' - '.$persona2->retornarEdad().'<br>';

Al ejecutarlo veremos que los datos que se imprimen son distintos.

Hay que diferenciar bien que el operador de asignación "=" no crea un nuevo objeto sino una nueva referencia a dicho objeto. Si queremos crear un nuevo objeto idéntico a uno ya existente debemos emplear el operador clone.

Cuando pasamos a un método un objeto lo que estamos pasando en realidad es la referencia a dicho objeto (no se crea un nuevo objeto)

Retornar