Menu
Coddy logo textTech

Análise Profunda da Clonagem de Objetos

Parte da seção Programação Orientada a Objetos do Journey de PHP da Coddy. Lição 61 de 91.

Você aprendeu sobre o método mágico __clone anteriormente neste curso. Agora, vamos explorar a diferença crucial entre clonagem superficial e profunda quando os objetos contêm outros objetos como propriedades.

Por padrão, PHP realiza uma cópia superficial ao clonar. Os valores escalares são duplicados, mas as propriedades dos objetos permanecem como referências aos mesmos 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;

Saída:

Alice - London

Observe que alterar $clone->name não afetou o original, mas alterar a cidade do endereço afetou! Ambos os objetos compartilham a mesma instância de Address.

Para criar uma cópia profunda em que os objetos aninhados também sejam clonados, implemente __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;

Saída:

Paris

Agora cada Person tem seu próprio Address independente. Quando seus objetos contêm vários objetos aninhados, você deve clonar cada um em __clone para alcançar uma verdadeira independência entre o original e a cópia.

challenge icon

Desafio

Fácil

Vamos criar um sistema de gerenciamento de documentos que demonstra a diferença entre clonagem superficial e profunda. Você criará documentos que contêm informações sobre o autor e garantirá que clonar um documento crie uma cópia verdadeiramente independente.

Você organizará seu código em três arquivos:

  • Author.php: crie uma classe Author que represente o autor de um documento. Use a promoção de propriedades no construtor para definir um $name público (string) e um $email público (string).
  • Document.php: crie uma classe Document que contenha um autor. Inclua o arquivo Author. A classe deve:
    • Usar a promoção de propriedades no construtor para um $title público (string) e um $author público (Author)
    • Implementar o método mágico __clone() para realizar uma clonagem profunda; quando um documento for clonado, seu autor também deverá ser clonado para que as alterações no autor da cópia não afetem o original
    • Ter um método getInfo() que retorne "[title] by [author name] ([author email])"
  • main.php: inclua o arquivo Document. Você receberá três entradas: o título de um documento, o nome de um autor e o e-mail de um autor.

    Crie um Document com um Author usando as entradas fornecidas. Clone o documento; em seguida, modifique o nome do autor da cópia acrescentando " (Copy)" a ele e altere o título da cópia acrescentando "Copy of " no início.

    Imprima duas linhas:

    • As informações do documento original
    • As informações do documento clonado

    Se a clonagem profunda tiver sido implementada corretamente, o autor do documento original deverá permanecer inalterado mesmo após a modificação do autor da cópia.

Este desafio demonstra por que a clonagem profunda é importante: sem a implementação adequada de __clone(), ambos os documentos compartilhariam o mesmo objeto Author, e alterar um afetaria o outro.

Experimente você mesmo

<?php

require_once 'Document.php';

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

// TODO: Crie um Author com o nome e o email fornecidos

// TODO: Crie um Document com o título fornecido e o Author

// TODO: Clone o documento

// TODO: Modifique o nome do autor do clone acrescentando " (Copy)" a ele

// TODO: Modifique o título do clone prefixando "Copy of " a ele

// TODO: Imprima as informações do documento original

// TODO: Imprima as informações do documento clonado

?>
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de PHP online