Reconozco que no había oído hablar de esta característica de PHP 5 hasta estas navidades, cuando un experimentado programador php me comentó que era algo que debía aprender (el mismo que me recomendó aprender Symphony, por cierto). La verdad es que el nombre suena rimbobante: «Métodos mágicos»… te quedas como «no se si será una decepción o si será la leche». Luego, curiosamente durante el transcurso de una entrevista laboral me volvieron a preguntar si sabía del tema, así que decidí informarme.
Tras leer sobre el tema he de decir que no me queda muy claro del todo el uso de dichos métodos. Se trata de una serie de métodos comunes a todas las clases que se crearon para PHP5 y que refuerzan la orientación a objetos del lenguaje. Estos métodos comienzan su nombre con __ por lo que se recomienda no crear métodos propios que empiecen así. Los citados métodos mágicos son:
- __construct()
- __destruct()
- __call()
- __callStatic()
- __get()
- __set()
- __isset()
- __unset()
- __sleep()
- __wakeup()
- __toString()
- __invoke()
- __setState()
- __clone()
Si has programado en Java unos cuántos ya te sonarán, porque no es sólo que se llamen igual, es que tienen una funcionalidad similar.
Por lo que he entendido leyendo la documentación, el método __sleep() es llamado cuando se utiliza el método serialize(), se ejecuta antes de comenzar la serialiación y nos permite definir un array con los nombres de todas las variables del objeto que se va a serializar. Por su parte __wakeup() nos permitiría reinicilizar el objeto después de la serialización (restablecer conexiones a la base de datos, por ejemplo), y se ejecuta cuando se utliza unserialize().
Por su parte __invoke() es llamado cuando se intenta llamar a un objeto como si fuera una función. Sí, suena raro, así que os pongo un ejemplo:
<?php class CallableClass { public function __invoke($x) { var_dump($x); } } $obj = new CallableClass; $obj(5); ?> //esto devolvería int(5)
En cuanto a __toString(), nos permite decidir qué se imprimirá si el objeto es llamado como si fuera una cadena de texto. Por ejemplo, si haces echo $objeto.
<?php class TesteandoToString { public $imprimir; public function __construct($imprimir) { $this->imprimir = $imprimir; } public function __toString() { return $this->imprimir; } } $class = new TesteandoToString('Hola caracola'); echo $class; //esto imprimiría Hola caracola ?>
El método __set_state() nos permite recoger un array con las variables exportadas por el método var_export() y asignarlas a un nuevo objeto. No confundir con la funcionalidad del método __clone(), que directamente crea una copia exacta de otro objeto.
Los métodos __call(), __callStatic(), __set(), __get(), __isset() y __unset() se utilizan para la sobrecarga, lo que nos permite «crear» dinámicamente propiedades y métodos. A estos métodos no se les pueden pasar parámetros por referencia. Se invoca a estos métodos cuando queremos trabajar con propiedades o métodos que no se han declarado o que no son visibles. El funcionamiento de __get() y __set() es similar al que pueden tener en Java los métodos get() y set(): el primero nos permite acceder a las propiedades privadas del objeto desde fuera de la clase y el segundo nos permite modificarlos. Puedes imaginar que __unset() lo que hará será «limpiar» de valor la propiedad y que __isset() funciona como isset() pero permitiendo el acceso a los valores privados. En cuanto a __call(), nos permitirá llamar a métodos inaccesibles en un contexto de objeto, y __callStatic() lo mismo pero en un contexto estático.
Finalmente __construct() es un método constructor, y será lo primero que se ejecute al crear un nuevo objeto de la clase, y __destruct() será lo último que se ejecute antes de eliminar el objeto de la memoria.
En fin, con todos estos métodos está claro que PHP gana mucho en cuanto a orientación a objetos.
Que poca originalidad, Dios mío. Ya que alguien se toma la molestia de escribir un lenguaje… ¿no sería lo más correcto escoger un camino propio y alejarse de los demás?
Puede que quisieran ceñirse al principio de «mínima sorpresa» para que los programadores en Java y C++ pudieran adaptarse rápido (un poco lo que hizo Matz cuando creó Ruby y lo intentó acercar a C). Pero sí, es innegable que es muy similar a Java, al menos en lo que respecta a sobrecarga.