Ver Mensaje Individual
  #11 (permalink)  
Antiguo 19/09/2008, 18:33
califa010
 
Fecha de Ingreso: enero-2006
Ubicación: Buenos Aires, Argentina
Mensajes: 299
Antigüedad: 18 años, 4 meses
Puntos: 5
Respuesta: Comparando objetos

Yo creo que el manual es un poco confuso en cuanto a cómo funcionan las referencias, y en especial cuando dice que los objetos se pasan por referencia.

Yo no diría que una instancia de un objeto se pasa por referencia, sino que la referencia a un objeto se pasa por valor. Parece un juego de palabras, pero para mí hay una diferencia que se puede ver más claramente con un ejemplo.

Código PHP:
function modificarProp($p_obj) {
    
$p_obj->foo "bar";
}

$obj = new stdClass();
$obj->foo "foo";
modificarProp($obj);
echo 
$obj->foo// imprime "bar" 
Hasta ahí, nada raro. Pero:

Código PHP:
function modificarProp($p_obj) {
    
$p_obj = new stdClass();
    
$p_obj->foo "bar";
}

$obj = new stdClass();
$obj->foo "foo";
modificarProp($obj);
echo 
$obj->foo// imprime "foo", no "bar" 
Si los objetos se pasaran realmente por referencia, debería imprimir "bar" y no "foo".

Yo diría entonces que una referencia es un "vínculo" a un objeto. Ese vínculo o referencia se puede guardar en una variable. De-referenciando ese vínculo, se puede acceder al contenido del objeto y modificarlo, pero lo que se pasa como argumento a una función es el valor de ese vínculo. Ese valor está contenido en una variable local, con la cual se pueden hacer básicamente 2 cosas:

1) De-refenciarlo (o sea, usar la sintaxis "->") para acceder a alguna propiedad del objeto original.
2) Asignar una nueva referencia o "vínculo" a esa variable local, con lo cual el objeto orignal no se modifica. Simplemente, perdemos el vínculo.

En esto creo que Php es igual muchos otros lenguajes, como Java, Actionscript, Javascript, Python, etc (por nombrar algunos que conozco en alguna medida). Pero, además, Php permite pasar referencias por referencias, usando el operador "&" (como se puede hacer en C# con "ref" y en C con punteros a punteros; dicho sea de paso, el manual se encarga de aclarar que las referencias no son para nada como los punteros en C, y si bien un puntero es una dirección de memoria y un referencia en php, no, en la mayoría de los casos -- o al menos en los ejemplos que siguen -- la "semántica" es la misma).

Ejemplos de paso de referencias por valor y por referencia.

Código PHP:
function referenciaPasadaPorValor($obj1,$obj2) {
    
$obj1 = new stdClass();
    
$obj1->foo "bar";
    
    
$obj2->foo "bar";
}

function 
referenciaPasadaPorReferencia(&$obj1,&$obj2) {
    
$obj1 = new stdClass();
    
$obj1->foo "bar";
    
    
$obj2->foo "bar";
}

$obj1 = new stdClass();
$obj2 = new stdClass();
$obj1->foo "foo";
$obj2->foo "foo";

referenciaPasadaPorValor($obj1,$obj2);
echo 
'$obj1->foo : ' $obj1->foo '<br>'// imprime foo
echo '$obj2->foo : ' $obj2->foo '<br>'// imprime bar



$obj1 = new stdClass();
$obj2 = new stdClass();
$obj1->foo "foo";
$obj2->foo "foo";
referenciaPasadaPorReferencia($obj1,$obj2);
echo 
'$obj1->foo : ' $obj1->foo '<br>'// imprime bar
echo '$obj2->foo : ' $obj2->foo '<br>'// imprime bar 

Saludos
Juan Pablo Califano