CÓDIGO: el contenido de un objeto se cambia después de ejecutar una función

El problema es que el contenido de $oldpop se cambia mágicamente después de ejecutar la función func, mientras que la entrada de func is $matepop. Dentro func, $oldpop no se usa (agregué la línea de comentarios para mostrar el lugar; vea el final del fragmento de código de PRINCIPAL.PHP). A continuación, proporciono solo algunas partes principales del código. Tal vez, ¿alguien podría sugerir la razón del problema?

Debo mencionar que no uso variables estáticas.

Archivo PRINCIPAL.PHP

include_once 'func.php';
include_once 'select.php';

class Individual {
    private $genes;
    private $rank;

    public function __construct() {
          $this->genes = array();
          $this->rank = 0;
    }

    public function setRank($val){
            $this->rank = $val;
    }

    public function setGene($i,$val){
        $this->genes[$i] = $val;
    }
}

class Population {
    private $ind;

    public function __construct()
    {
        $this->ind = array();
    }

    public function addIndividual(Individual $ind)
    {
        $this->ind[] = $ind;
    }

    public function getIndividual($i){
        return $this->ind[$i];
    }
  }


    $oldpop = new Population();

  for($i=0; $i<$popsize; $i++) {
    $oldpop->addIndividual(new Individual());
  }

    $oldpop = func($oldpop,$popsize); 

    for ($i = 0; $i < $gener; $i++) 
    {        
        $matepop = new Population();
        $matepop = nselect($matepop,$oldpop,$popsize);

        // !!! Here the $oldpop content is correct (original)
        $matepop = func($matepop,$popsize);
        // !!!! Here the original content of $oldpop is magically changed

    }

Archivo SELECCIONAR.PHP

function nselect($matepop,$oldpop,$popsize) { 
  $select = array();
  //...
  $select[] = $oldpop->getIndividual($i);
  //...
  for ($i=0; $i < $popsize; $i++) {
       $matepop->addIndividual($select[$i]);
  }
  return $matepop;
}

Archivo FUNC.PHP

function func($pop,$popsize) { 
  //...
  $pop->getIndividual($i)->setRank($val);
  //...
  return $pop;
}

preguntado el 10 de septiembre de 12 a las 22:09

Cualquier razón específica por la cual $matepop se sobrescribe con new Population(); ? Asumo $gener tiene un valor mayor que 1? -

Sí exactamente. $gener tiene valor 10. Pero este problema ya ocurre en $i = 0 (me refiero a $i -> contador para $gener). -

Mirando a través de todo ese código, solo vi setRank apareció una vez, y fue entonces cuando lo llamaste. Supongo que tienes un setRank método en algún lugar de su Individual ¿clase? -

@dbf: en cada $i necesito crear un nuevo $matepop. Pero incluso si hago $matepop = new Popolation() antes del ciclo 0-$gener FOR, el problema descrito en el hilo aún existe. -

@Palladium: sí, correctamente: dentro de la clase Individual que tengo - $ rango privado; public function setRank($val){ $this->rank = $val; } -

2 Respuestas

Las variables de objeto de PHP no contienen una copia completa del objeto; más bien, contienen una referencia al objeto. Esto significa que cuando usó

$select[] = $oldpop->getIndividual($i);

en su código, no hizo una nueva copia del objeto $i; simplemente copió la referencia al objeto $i en la matriz $select. Esto significa que ambos $oldpop y $matepop contienen referencias a la mismo objetos en su $ind arreglos Luego, cuando más tarde usó

$pop->getIndividual($i)->setRank($val);

para establecer el rango de cada Individual-clase objeto en $matepop, también cambiaron por $oldpop.

Respondido el 10 de Septiembre de 12 a las 22:09

En su nselect() función, obtienes personas de $oldpop y luego agregarlos a $matepop:

$select[] = $oldpop->getIndividual($i);
//...
for ($i=0; $i < $popsize; $i++) {
    $matepop->addIndividual($select[$i]);
}

Cuando hace esto, esto no "crea una copia" del individual y agregue la copia - agrega un referencia al original Entonces, hagas lo que hagas para cualquier de los individuals añadido a $matepop a través de este método se actualizará en consecuencia en $oldpop también porque, bueno, son exactamente el mismo objeto.

Entonces, en tu func() método, cuando establece el rango en el individuals in $matepop (y supongo que esa es la única individual-modificación que realiza en esa función) está modificando la única instancia de cada individual, al que se hace referencia en $matepop y $oldpop. Por eso ves $oldpop modificado.

Para resolver un problema como este, deberá implementar algún tipo de clonar/copiar en lugar de una referencia directa.

Respondido el 10 de Septiembre de 12 a las 22:09

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.