lunes, 1 de febrero de 2016

Métodos mágicos en PHP 5

PHP 5, nos trae una gran cantidad de auto-denominados “métodos mágicos”. Estos métodos, otorgan una funcionalidad pre-definida por PHP, que pueden aportar valor a nuestras clases y ahorrarnos grandes cantidades de código. Lo que muchos programadores consideramos, ayuda a convertir a PHP en un lenguaje orientado a objetos, cada vez más robusto.
Entre los métodos mágicos, podemos encontrar los siguientes: 

El Método Mágico __construct()
El método __construct() es aquel que será invocado de manera automática, al instanciar un objeto. Su función es la de ejecutar cualquier inicialización que el objeto necesite antes de ser utilizado.

# declaro la clase
class Producto {
#defino algunas propiedades
public $nombre;
public $precio;
protected $estado;
#defino el método set_estado_producto()
protected function set_estado_producto($estado) {
$this->estado = $estado;
}
# constructor de la clase
function __construct() {
$this->set_estado_producto('en uso');
}
}

En el ejemplo anterior, el constructor de la clase se encarga de definir el estado del producto como “en
uso”, antes de que el objeto (Producto) comience a utilizarse. Si se agregaran otros métodos, éstos, podrán hacer referencia al estado del producto, para determinar si ejecutar o no determinada función. Por ejemplo, no podría mostrarse a la venta un producto “en uso por el sistema”, ya que a éste, se le podría estar modificando el precio.

El método mágico __destruct()
El método __destruct() es el encargado de liberar de la memoria, al objeto cuando ya no es referenciado. Se puede aprovechar este método, para realizar otras tareas que se estimen necesarias al momento de destruir un objeto.

# declaro la clase
class Producto {
#defino algunas propiedades
public $nombre;
public $precio;
protected $estado;
#defino el método set_estado_producto()
protected function set_estado_producto($estado) {
$this->estado = $estado;
}
# constructor de la clase
function __construct() {
$this->set_estado_producto('en uso');
}
# destructor de la clase
function __destruct() {
$this->set_estado_producto('liberado');
print 'El objeto ha sido destruido';
}
}

Otros métodos mágicos
PHP nos ofrece otros métodos mágicos tales como __call, __callStatic, __get, __set, __isset, __unset, __sleep, __wakeup, __toString, __invoke, __set_state y __clone.
Puede verse una descripción y ejemplo de su uso, en el sitio Web oficial de PHP:

Métodos abstractos

A diferencia de las propiedades, los métodos, pueden ser abstractos como sucede con las clases.
El Manual Oficial de PHP, se refiere a los métodos abstractos, describiéndolos de la siguiente forma:

[…] “Los métodos definidos como abstractos simplemente declaran la estructura del método, pero no pueden definir la implementación. Cuando se hereda de una clase abstracta, todos los métodos definidos como abstract en la definición de la clase parent deben ser redefinidos en la clase child; adicionalmente, estos métodos deben ser definidos con la misma visibilidad (o con una menos restrictiva). Por ejemplo, si el método abstracto está definido como protected, la implementación de la función puede ser redefinida como protected o public, pero nunca como private.” […]

Para entender mejor los métodos abstractos, podríamos decir que a grandes rasgos, los métodos abstractos son aquellos que se declaran inicialmente en una clase abstracta, sin especificar el algoritmo que implementarán, es decir, que solo son declarados pero no contienen un “código” que específique qué harán y cómo lo harán.
Tal vez, te preguntes ¿Cuál es la utilidad de definir métodos abstractos y clases abstractas? Para responder a esta pregunta, voy enfocarme en un caso de la vida real:

Ejemplo

Se trataba de hacer un sistema de gestión informática, para las farmacias de los Hospitales. Un punto fundamental, era pensar en los insumos farmacéuticos como “un todo abstracto”. ¿Por qué? Fundamentalmente, porque si bien existen insumos farmacéuticos de todo tipo y especie, cada uno de ellos, comparte características comunes, que por sí solas no pueden definirse con precisión. Por ejemplo, todos los insumos farmacéuticos requieren de un tipo de conservación especial. Algunos requieren refrigeración a determinada temperatura que solo puede ser satisfecha conservándolos en una
heladera; otros requieren conservarse en un ambiente seco; otros, no pueden tomar contacto con el exterior, a fin de conservar su capacidad estéril; etc. ¿Podía definirse con exactitud una clase Insumo? La respuesta a esa pregunta, es justamente su pregunta retórica ¿irías a la farmacia a pedirle al farmacéutico “deme un insumo de 500 mg”? Insumo, representa la entidad “abstracta” y para eso, sirven las clases abstractas. Con ellas declaramos aquellos “objetos” que no pueden ser definidos con
presición pero aseguramos allí, todas aquellas características que dichos objetos, guardarán entre sí. Declarar un método conservar_insumo() como abstracto, serviría para luego definir con exactitud, en una clase heredada, el algoritmo exacto que determinado insumo necesitaría para procesar su conservación. Es así entonces, que una clase InsumoRefrigerado heredaría de Insumo, y redefiniría el método conservar_insumo() indicando un algoritmo que solicitara la temperatura a la cual debía conservarse en heladera, etc.

Métodos en PHP 5

Cabe recordar, para quienes vienen de la programación estructurada, que el método de una clase, es un algoritmo igual al de una función. La única diferencia entre método y función, es que llamamos método a las funciones de una clase (en la POO), mientras que llamamos funciones, a los algoritmos de la programación estructurada.

Reglas de Estilo sugeridas

Utilizar nombres_de_funciones_descriptivos, en letra minúscula, separando palabras por guiones bajos, ayuda a comprender mejor el código fuente haciéndolo más intuitivo y legible.
La forma de declarar un método es anteponiendo la palabra clave function al nombre del método, seguido por un par paréntesis de apertura y cierre y llaves que encierren el algoritmo:

# declaro la clase
class Persona {
#propiedades
#métodos
function donar_sangre() {
#...
}
}

Al igual que cualquier otra función en PHP, los métodos recibirán los parámetros necesarios indicando aquellos requeridos, dentro de los paréntisis:

# declaro la clase
class Persona {
#propiedades
#métodos
function donar_sangre($destinatario) {
#...
}
}

Métodos públicos, privados, protegidos y estáticos

Los métodos, al igual que las propiedades, pueden ser públicos, privados, protegidos o estáticos. La forma de declarar su visibilidad tanto como las características de ésta, es exactamente la misma que para las propiedades.

static function a() { }
protected function b() { }
private function c() { }
# etc...

Accediendo a las propiedad de un objeto

Para acceder a las propiedad de un objeto, existen varias maneras de hacerlo. Todas ellas, dependerán del ámbito desde el cual se las invoque así como de su condición y visibilidad.

Acceso a variables desde el ámbito de la clase

Se accede a una propiedad no estática dentro de la clase, utilizando la pseudo-variable $this siendo esta pseudo-variable una referencia al objeto mismo:

return $this->nombre;

Cuando la variable es estática, se accede a ella mediante el operador de resolución de ámbito, doble dos-puntos :: anteponiendo la palabra clave self o parent según si trata de una variable de la misma clase o de otra de la cual se ha heredado, respectivamente:

print self::$variable_estatica_de_esta_clase;
print parent::$variable_estatica_de_clase_madre;

Acceso a variables desde el exterior de la clase
Se accede a una propiedad no estática con la siguiente sintáxis: 

$objeto->variable

Nótese además, que este acceso dependerá de la visibilidad de la variable. Por lo tanto, solo variables públicas pueden ser accedidas desde cualquier ámbito fuera de la clase o clases heredadas.

# creo el objeto instanciando la clase
$persona_a_positivo = new PersonaAPositivo();
# accedo a la variable NO estática
print $persona_a_positivo->nombre;

Para acceder a una propiedad pública y estática el objeto no necesita ser instanciado, permitiendo así, el acceso a dicha variable mediante la siguiente sintáxis:

Clase::$variable_estática
# accedo a la variable estática
print PersonaAPositivo::$tipo_sangre;

Constantes de Clase
Otro tipo de “propiedad” de una clase, son las constantes, aquellas que mantienen su valor de forma permanente y sin cambios. A diferencia de las propiedades estáticas, las constantes solo pueden tener una visibilidad pública.
Puede declararse una constante de clase como cualquier constante normal en PHP 5. El acceso a constantes es exactamente igual que al de otras propiedades.

Reglas de Estilo sugeridas

Utilizar NOMBRE_DE_CONSTANTE en letra MAYÚSCULA, ayuda a diferenciar rápidamente constantes de variables, haciendo más legible el código.

const MI_CONSTANTE = 'Este es el valor estático de mi constante';