Modelo de objetos en PHP5

Referencias, manejadores, handlers

Los objetos en PHP5 son referenciados a través de manejadores (handlers, referencias).

Como consecuencia de esta característica, cuando se hace una asignación de un objeto en realidad sólo se duplica el manejador (referencia) y no el objeto completo como sucedía antes en PHP4.

Lo podemos ver en el siguiente ejemplo en el que se define una clase Vehiculo.

//// Clase Vehiculo
class Vehiculo
{
//// atributos publicos
public $velocidadMaxima;
public
$potencia;
public
$color;
public
$peso;

//// constructor
function __construct($potencia,$peso)
{
$this->potencia = $potencia;
$this->peso = $peso;

return
true;

}

//// metodo relacionPesoPotencia()
function relacionPesoPotencia()
{
if (
$this->potencia>0)
{
return (
$this->peso/$this->potencia);
}

return -
1;
}

}
//// termina def. clase Vehiculo

 

Creamos una instancia de la clase, es decir, un objeto de tipo Vehiculo con unas determinadas características (atributos). Con la sentencia $obj_alias = $obj_vehiculo estamos creando un alias del objeto (duplicamos el manejador). Cualquier operación sobre $obj_alias afecta a las características de $obj_vehiculo.

//// creamos un vehiculo (5 CV, 80 Kg)
$obj_vehiculo = new Vehiculo(5,80);
echo
$obj_vehiculo->relacionPesoPotencia()."<br>";
//// muestra 16

//// PHP5:
//// asignacion de objetos = asignacion de manejadores (handlers)
$obj_alias = $obj_vehiculo;
echo
$obj_alias->relacionPesoPotencia()."<br>";
//// muestra 16

//// los dos manejadores referencian al mismo objeto
$obj_alias->peso = 60;
echo
$obj_vehiculo->relacionPesoPotencia()."<br>";
//// muestra 12

echo $obj_alias->relacionPesoPotencia()."<br>";
//// muestra 12

Gráficamente el proceso es el siguiente:

Lo mismo ocurre con los objetos pasados como parámetros a las funciones: siempre se pasan por referencia puesto que con lo que se trabaja dentro de la función es un duplicado del manejador original del objeto.

En el ejemplo se define una función kitDePotencia() que recibe como parámetro una copia del manejador del objeto. La variable $vehiculo referencia por tanto al objeto original.

//// funcion kitDePotencia ()
//// Aumenta la potencia de un vehiculo
function kitDePotencia($vehiculo)
{
$vehiculo->potencia = $vehiculo->potencia + 5;

return
true;
}


//// creamos un objeto vehiculo (5 CV, 80 Kg)
$obj_vehiculo = new Vehiculo(5,80);
echo
$obj_vehiculo->relacionPesoPotencia()."<br>";
//// muestra 16

//// aumentamos potencia
kitDePotencia ($obj_vehiculo);

echo
$obj_vehiculo->relacionPesoPotencia()."<br>";
//// ahora muestra 8

En el caso de que realmente necesitemos copiar objetos (clonar) tendremos que recurrir a la llamada al método especial __clone (la implementación del constructor de copia para el modelo de objetos de PHP5).

 

Constructor / Destructor

Los diseñadores del núcleo de PHP5 (Zend Engine 2) han optado por un modelo homogéneo para los constructores de las clases. El método constructor de una clase siempre se define como __construct( ). Este método se encarga de llevar a cabo la inicialización del objeto cuando éste es instanciado a partir de su clase.

  //// constructor
function __construct($potencia,$peso)
{
$this->potencia = $potencia;
$this->peso = $peso;

return
true;

}

Por compatibilidad con versiones anteriores de PHP, el compilador busca en primer lugar el constructor estándar __construct() y si no lo encuentra busca un método cuyo nombre coincide con el de la clase. Esto permite que las clases creadas para PHP4 puedan funcionar con el nuevo Zend Engine 2.

El hecho de que todos los constructores tengan el mismo nombre facilita la llamada al constructor de la clase base desde su clase derivada.

En PHP5 también se incorpora el concepto de destructor. El destructor es un método llamado __destruct() que se ejecuta justo antes de que el objeto sea eliminado de memoria. En PHP5 un objeto desaparece cuando ya no es referenciado, es decir, cuando todos sus manejadores han desaparecido.

El método destructor puede ser utilizado para conseguir que los objetos desaparezcan de una forma 'limpia', por ejemplo comprobando que se ha cerrado un manejador de fichero abierto por el objeto, para actualizar o comprobar algún elemento de la base de datos, para cerrar conexiones con bases de datos, etc...