Menu
Coddy logo textTech

Mergulho Profundo em 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 __clone method mágico anteriormente neste curso. Agora vamos explorar a diferença crítica entre a clonagem superficial e deep 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 document que demonstra a diferença entre clonagem superficial e clonagem profunda. Você criará document que contêm informações de author e garantirá que clonar um document crie uma cópia realmente independente.

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

  • Author.php: Crie uma classe Author que represente o author de um document. Use constructor promotion para definir um $name público (string) e um $email público (string).
  • Document.php: Crie uma classe Document que contenha um author. Inclua o arquivo Author. A classe deve:
    • Usar constructor promotion para um $title público (string) e um $author público (Author)
    • Implementar o método mágico __clone() para realizar cloning profundo; quando um document é clonado, seu author também deve ser clonado, para que as alterações no author do clone não afetem o original
    • Ter um method getInfo() que returns "[title] by [author name] ([author email])"
  • main.php: Inclua o arquivo Document. Você receberá três entradas: um título de document, um nome de author e um email de author.

    Crie um Document com um Author usando os inputs provided. Clone o document e, em seguida, modifique o nome do author do clone appending " (Copy)" a ele e altere o título do clone prepending "Copy of " a ele.

    Print duas linhas:

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

    Se o seu cloning profundo estiver implementado corretamente, o author do document original should permanecer inalterado mesmo após modificar o author do clone.

Este desafio demonstra por que o cloning profundo é importante: sem a implementação adequada de __clone(), ambos os document 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