Menu
Coddy logo textTech

Clonación de objetos a fondo

Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy. Lección 61 de 91.

Aprendiste sobre el __clone magic method anteriormente en este curso. Ahora exploremos la diferencia crítica entre la clonación shallow y deep cuando los objetos contienen otros objetos como propiedades.

De forma predeterminada, PHP realiza una copia superficial al clonar. Los valores escalares se duplican, pero las propiedades de los objetos permanecen como referencias a los mismos objetos:

<?php
class Address {
    public function __construct(public string $city) {}
}

class Person {
    public function __construct(
        public string $name,
        public Address $address
    ) {}
}

$original = new Person("Alice", new Address("Paris"));
$clone = clone $original;

$clone->name = "Bob";
$clone->address->city = "London";

echo $original->name . " - " . $original->address->city;

Salida:

Alice - London

Observa que cambiar $clone->name no afectó a original, ¡pero cambiar la ciudad de address sí! Ambos objetos comparten la misma instancia de Address.

Para crear una copia profunda en la que los objetos anidados también se clonen, implementa __clone:

<?php
class Person {
    public function __construct(
        public string $name,
        public Address $address
    ) {}
    
    public function __clone(): void {
        $this->address = clone $this->address;
    }
}

$original = new Person("Alice", new Address("Paris"));
$clone = clone $original;
$clone->address->city = "London";

echo $original->address->city;

Salida:

Paris

Ahora cada Person tiene su propio Address independiente. Cuando tus objetos contienen varios objetos anidados, debes clonar cada uno en __clone para lograr una verdadera independencia entre el objeto original y la copia.

challenge icon

Desafío

Fácil

Construyamos un sistema de gestión de documentos que demuestre la diferencia entre la clonación superficial y profunda. Crearás documentos que contengan información del autor y te asegurarás de que clonar un documento cree una copia verdaderamente independiente.

Organizarás tu código en tres archivos:

  • Author.php: Crea una clase Author que represente al autor de un documento. Usa la promoción de constructor para definir un $name (string) public y un $email (string) public.
  • Document.php: Crea una clase Document que contenga un author. Incluye el archivo Author. La clase should:
    • Usar la promoción de constructor para un $title (string) public y un $author (Author) public
    • Implementar el método magic __clone() para realizar una clonación profunda; cuando se clone un document, su author también should clonarse para que los cambios en el author del clon no afecten al original
    • Tener un method getInfo() que returns "[title] by [author name] ([author email])"
  • main.php: Incluye el archivo Document. Recibirás tres inputs: el título de un document, el nombre de un author y el email de un author.

    Crea un Document con un Author usando los inputs provided. Clona el document, después modifica el nombre del author del clon appending " (Copy)" y cambia el título del clon prepending "Copy of ".

    Print dos líneas:

    • La info del document original
    • La info del document clonado

    Si la clonación deep está implementada correctamente, el author del document original should permanecer sin cambios incluso después de modificar el author del clon.

Este challenge demuestra por qué la clonación deep es importante: sin una implementación adecuada de __clone(), ambos documents compartirían el mismo objeto Author y cambiar uno afectaría al otro.

Pruébalo tú mismo

<?php

require_once 'Document.php';

// Leer entradas
$title = trim(fgets(STDIN));
$authorName = trim(fgets(STDIN));
$authorEmail = trim(fgets(STDIN));

// TODO: Crear un Author con el nombre y el email proporcionados

// TODO: Crear un Document con el título proporcionado y el Author

// TODO: Clonar el documento

// TODO: Modificar el nombre del autor del clon añadiendo " (Copy)" a él

// TODO: Modificar el título del clon anteponiendo "Copy of " a él

// TODO: Imprimir la info del documento original

// TODO: Imprimir la info del documento clonado

?>
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de PHP online