<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/language.oop5.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'es',
  ),
  'this' => 
  array (
    0 => 'language.oop5.cloning.php',
    1 => 'Clonaci&oacute;n de objetos',
    2 => 'Clonaci&oacute;n de objetos',
  ),
  'up' => 
  array (
    0 => 'language.oop5.php',
    1 => 'Clases y objetos',
  ),
  'prev' => 
  array (
    0 => 'language.oop5.final.php',
    1 => 'Palabra clave &quot;final&quot;',
  ),
  'next' => 
  array (
    0 => 'language.oop5.object-comparison.php',
    1 => 'Comparaci&oacute;n de objetos',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'es',
    'path' => 'language/oop5/cloning.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="language.oop5.cloning" class="sect1">
  <h2 class="title">Clonación de objetos</h2>

  <p class="simpara">
   La creación de una copia de un objeto con exactamente las mismas
   propiedades no siempre es el comportamiento deseado.
   Un buen ejemplo para ilustrar la necesidad de un constructor de copia:
   si se tiene un objeto que representa una ventana GTK y el objeto
   contiene el recurso que representa esa ventana GTK, al crear una copia,
   se puede desear crear una nueva ventana con las mismas propiedades,
   pero que el nuevo objeto contenga un recurso que represente la nueva ventana.
   Otro ejemplo: si el objeto contiene una referencia a otro objeto que
   utiliza, al replicar el objeto padre se puede desear crear una nueva
   instancia de ese otro objeto, de modo que la réplica tenga su propia copia
   independiente.
  </p>

  <p class="para">
   Una copia de objeto se crea utilizando la palabra clave <code class="literal">clone</code>
   (que invoca al método <a href="language.oop5.cloning.php#object.clone" class="link">__clone()</a>
   del objeto, si ha sido definido).
  </p>

  <div class="informalexample">
   <div class="example-contents">
<div class="cdata"><pre>
$copy_of_object = clone $object;
</pre></div>
   </div>

  </div>

  <p class="para">
   Cuando un objeto es clonado, PHP realiza una copia superficial de todas
   las propiedades del objeto. Todas las propiedades que son referencias a otras
   variables permanecerán como referencias.
  </p>

  <div class="methodsynopsis dc-description" id="object.clone">
   <span class="modifier">function</span> <span class="methodname"><strong>__clone</strong></span>(): <span class="type"><a href="language.types.void.php" class="type void">void</a></span></div>


  <p class="simpara">
   Una vez realizada la clonación, si se ha definido un método <a href="language.oop5.cloning.php#object.clone" class="link">__clone()</a>,
   el método <a href="language.oop5.cloning.php#object.clone" class="link">__clone()</a>
   del nuevo objeto será llamado, para permitir que cada propiedad que deba ser modificada lo sea.
  </p>

  <div class="example" id="example-1">
   <p><strong>Ejemplo #1 Ejemplo de duplicación de objetos</strong></p>
   <div class="example-contents">
<div class="phpcode"><pre><code style="color: #000000"><span style="color: #0000BB">&lt;?php
</span><span style="color: #007700">class </span><span style="color: #0000BB">SubObject
</span><span style="color: #007700">{
  static </span><span style="color: #0000BB">$instances </span><span style="color: #007700">= </span><span style="color: #0000BB">0</span><span style="color: #007700">;
  public </span><span style="color: #0000BB">$instance</span><span style="color: #007700">;

  public function </span><span style="color: #0000BB">__construct</span><span style="color: #007700">() {
    </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">instance </span><span style="color: #007700">= ++</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">$instances</span><span style="color: #007700">;
  }

  public function </span><span style="color: #0000BB">__clone</span><span style="color: #007700">() {
    </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">instance </span><span style="color: #007700">= ++</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">$instances</span><span style="color: #007700">;
  }
}

class </span><span style="color: #0000BB">MyCloneable
</span><span style="color: #007700">{
  public </span><span style="color: #0000BB">$object1</span><span style="color: #007700">;
  public </span><span style="color: #0000BB">$object2</span><span style="color: #007700">;

  function </span><span style="color: #0000BB">__clone</span><span style="color: #007700">()
  {
    </span><span style="color: #FF8000">// Fuerza la copia de this-&gt;object, de lo contrario
    // apuntará al mismo objeto.
    </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">object1 </span><span style="color: #007700">= clone </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">object1</span><span style="color: #007700">;
  }
}

</span><span style="color: #0000BB">$obj </span><span style="color: #007700">= new </span><span style="color: #0000BB">MyCloneable</span><span style="color: #007700">();

</span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">object1 </span><span style="color: #007700">= new </span><span style="color: #0000BB">SubObject</span><span style="color: #007700">();
</span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">object2 </span><span style="color: #007700">= new </span><span style="color: #0000BB">SubObject</span><span style="color: #007700">();

</span><span style="color: #0000BB">$obj2 </span><span style="color: #007700">= clone </span><span style="color: #0000BB">$obj</span><span style="color: #007700">;

print </span><span style="color: #DD0000">"Objeto original:\n"</span><span style="color: #007700">;
</span><span style="color: #0000BB">print_r</span><span style="color: #007700">(</span><span style="color: #0000BB">$obj</span><span style="color: #007700">);

print </span><span style="color: #DD0000">"Objeto clonado:\n"</span><span style="color: #007700">;
</span><span style="color: #0000BB">print_r</span><span style="color: #007700">(</span><span style="color: #0000BB">$obj2</span><span style="color: #007700">);

</span><span style="color: #0000BB">?&gt;</span></code></pre></div>
   </div>

   <div class="example-contents"><p>El ejemplo anterior mostrará:</p></div>
   <div class="example-contents screen">
<div class="cdata"><pre>
Objeto original:
MyCloneable Object
(
    [object1] =&gt; SubObject Object
        (
            [instance] =&gt; 1
        )

    [object2] =&gt; SubObject Object
        (
            [instance] =&gt; 2
        )

)
Objeto clonado:
MyCloneable Object
(
    [object1] =&gt; SubObject Object
        (
            [instance] =&gt; 3
        )

    [object2] =&gt; SubObject Object
        (
            [instance] =&gt; 2
        )

)
</pre></div>

   </div>

  </div>

  <p class="para">
   Es posible acceder a un miembro de un objeto
   recién clonado en una sola expresión:
  </p>
  <div class="example" id="example-2">
   <p><strong>Ejemplo #2 Acceso a un miembro de un objeto recién clonado</strong></p>
   <div class="example-contents">
<div class="phpcode"><pre><code style="color: #000000"><span style="color: #0000BB">&lt;?php
$dateTime </span><span style="color: #007700">= new </span><span style="color: #0000BB">DateTime</span><span style="color: #007700">();
echo (clone </span><span style="color: #0000BB">$dateTime</span><span style="color: #007700">)-&gt;</span><span style="color: #0000BB">format</span><span style="color: #007700">(</span><span style="color: #DD0000">'Y'</span><span style="color: #007700">);
</span><span style="color: #0000BB">?&gt;</span></code></pre></div>
   </div>

   <div class="example-contents"><p>Resultado del ejemplo anterior
es similar a:</p></div>
   <div class="example-contents screen">
<div class="cdata"><pre>
2016
</pre></div>
   </div>
  </div>

  <div class="sect2" id="language.oop5.cloning.with-properties">
   <h3 class="title">Clonación con sustitución de propiedades</h3>

   <p class="simpara">
    A partir de PHP 8.5.0, <code class="literal">clone</code> también está disponible como
    función, cuyo segundo parámetro <code class="parameter">withProperties</code> acepta
    un array que asocia nombres de propiedades con los valores que recibe la
    copia. Solo se sustituyen las propiedades indicadas; las demás conservan el
    valor con el que fueron copiadas.
   </p>

   <p class="simpara">
    Las sustituciones se aplican después de la ejecución de
    <a href="language.oop5.cloning.php#object.clone" class="link">__clone()</a> y respetan la visibilidad de
    todas las propiedades.
    Las <a href="language.oop5.properties.php#language.oop5.properties.readonly-properties" class="link">propiedades readonly</a>
    pueden modificarse en la copia aunque ya estuvieran inicializadas en el
    objeto original, lo que hace que la función resulte adecuada para los
    métodos que devuelven una copia modificada.
   </p>

   <div class="example" id="example-3">
    <p><strong>Ejemplo #3 Clonación de un objeto con sustitución de propiedades</strong></p>
    <div class="example-contents">
<div class="phpcode"><pre><code style="color: #000000"><span style="color: #0000BB">&lt;?php
</span><span style="color: #007700">class </span><span style="color: #0000BB">Point </span><span style="color: #007700">{
    public function </span><span style="color: #0000BB">__construct</span><span style="color: #007700">(
        public readonly </span><span style="color: #0000BB">int $x</span><span style="color: #007700">,
        public readonly </span><span style="color: #0000BB">int $y</span><span style="color: #007700">,
    ) {}

    public function </span><span style="color: #0000BB">withX</span><span style="color: #007700">(</span><span style="color: #0000BB">int $x</span><span style="color: #007700">): static
    {
        return clone(</span><span style="color: #0000BB">$this</span><span style="color: #007700">, [</span><span style="color: #DD0000">'x' </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">$x</span><span style="color: #007700">]);
    }
}

</span><span style="color: #0000BB">$p </span><span style="color: #007700">= new </span><span style="color: #0000BB">Point</span><span style="color: #007700">(</span><span style="color: #0000BB">1</span><span style="color: #007700">, </span><span style="color: #0000BB">2</span><span style="color: #007700">);
</span><span style="color: #0000BB">$q </span><span style="color: #007700">= </span><span style="color: #0000BB">$p</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">withX</span><span style="color: #007700">(</span><span style="color: #0000BB">10</span><span style="color: #007700">);

echo </span><span style="color: #0000BB">$q</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">x</span><span style="color: #007700">, </span><span style="color: #DD0000">' '</span><span style="color: #007700">, </span><span style="color: #0000BB">$q</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">y</span><span style="color: #007700">;
</span><span style="color: #0000BB">?&gt;</span></code></pre></div>
    </div>

    <div class="example-contents"><p>El ejemplo anterior mostrará:</p></div>
    <div class="example-contents screen">
<div class="cdata"><pre>
10 2
</pre></div>
    </div>
   </div>
  </div>

</div><?php manual_footer($setup); ?>