## Abstracción de clases

PHP 5 introduce clases y métodos abstractos. Las clases definidas como abstractas no se pueden instanciar y cualquier clase que contiene al menos un método abstracto debe ser definida como tal. Los métodos definidos como abstractos simplemente declaran la firma del método, pero no pueden definir la implementación.

Cuando se hereda de una clase abstracta, todos los métodos definidos como abstractos en la declaración de la clase madre deben ser definidos en la clase hija; además, estos métodos deben ser definidos con la misma (o con una menos restrictiva) visibilidad. Por ejemplo, si el método abstracto está definido como protegido, la implementación de la función debe ser definida como protegida o pública, pero nunca como privada. Por otra parte, las firmas de los métodos tienen que coincidir, es decir, la declaración de tipos y el número de argumentos requeridos deben ser los mismos. Por ejemplo, si la clase derivada define un argumento opcional y la firma del método abstracto no lo hace, no habría conflicto con la firma. Esto también se aplica a los constructores a partir de PHP 5.4. Antes de PHP 5.4, las firmas del constructor podían ser diferentes.

Ejemplo #1 Ejemplo de clase abstracta

`<?php
abstract class ClaseAbstracta
{
// Forzar la extensión de clase para definir este método
abstract protected function getValor();
abstract protected function valorPrefijo($prefijo);
// Método común
public function imprimir() {
print $this->getValor() . "\n";
}
}
class ClaseConcreta1 extends ClaseAbstracta
{
protected function getValor() {
return "ClaseConcreta1";
}
public function valorPrefijo($prefijo) {
return "{$prefijo}ClaseConcreta1";
}
}
class ClaseConcreta2 extends ClaseAbstracta
{
public function getValor() {
return "ClaseConcreta2";
}
public function valorPrefijo($prefijo) {
return "{$prefijo}ClaseConcreta2";
}
}
$clase1 = new ClaseConcreta1;
$clase1->imprimir();
echo $clase1->valorPrefijo('FOO_') ."\n";
$clase2 = new ClaseConcreta2;
$clase2->imprimir();
echo $clase2->valorPrefijo('FOO_') ."\n";
?>`

El resultado del ejemplo sería:

    ClaseConcreta1
    FOO_ClaseConcreta1
    ClaseConcreta2
    FOO_ClaseConcreta2

Ejemplo #2 Ejemplo de clase abstracta

`<?php
abstract class ClaseAbstracta
{
// El método abstracto sólo necesita definir los argumentos requeridos
abstract protected function nombrePrefijo($nombre);
}
class ClaseConcreta extends ClaseAbstracta
{
// La clase derivada puede definir parámetros opcionales que no estén en la estructura del prototipo
public function nombrePrefijo($nombre, $separador = ".") {
if ($nombre == "Pacman") {
$prefijo = "Mr";
} elseif ($nombre == "Pacwoman") {
$prefijo = "Mrs";
} else {
$prefijo = "";
}
return "{$prefijo}{$separador} {$nombre}";
}
}
$clase = new ClaseConcreta;
echo $clase->nombrePrefijo("Pacman"), "\n";
echo $clase->nombrePrefijo("Pacwoman"), "\n";
?>`

El resultado del ejemplo sería:

    Mr. Pacman
    Mrs. Pacwoman

El código antiguo que no tenga clases o funciones definidas por el usuario llamadas 'abstract' deberían ejecutarse sin modificaciones.