PHP orientado a objetos 8: clases abstractas y finales

En esta entrada conoceremos dos tipos especiales de clases: las abstractas y las finales.

hiroshige

archivado en: PHP/AJAX / 24 marzo, 2013 / taller:

Hace un par de entradas vimos qué es la herencia, un concepto clave de la programación orientada a objetos, que en esencia consiste en traspasar, en extender, los métodos y propiedades de una clase a otra. En esta trataré de explicar dos  tipos de clase especial que hay en PHP en función de esta característica.

¡Qué abstracta es la abstracción!

En programación, se habla de «abstracción» para referirse a elementos que definen comportamientos independientemente de su concreción. Por ejemplo, pensemos en un algoritmo que sirve para apagar y encender.

abstracción de interruptor {

if ( estado == 0 ) {

apaga;

} else if ( estado == 1 )

enciende;

}

Este algoritmo interruptor se limita a comprobar un estado y, en función de eso, apagar o encender. Es un modelo abstracto que se puede emplear, concretar, en una radio, un submarino, la luz de una biblioteca o una lavadora... en fin, en cualquier cosa que se apague y se encienda.

Otro ejemplo retomando los dinosaurios con los que empecé esta serie. Todo dinosaurio tiene unas características comunes: nace, se reproduce —o al menos lo intenta— y muere. Por lo tanto, podríamos formular una abstracción de dinosaurio a partir de estos datos:

abstracción de dinosaurio {

var Tiempo de vida;

var Hormonas revolucionadas;

var Tiempo de muerte;

function existenciaDinosauril {

if  ( Tiempo de vida == Tiempo de muerte )

return dinosaurio fiambre;

} else if (  Tiempo de vida == Hormonas revolucionadas ) {

buscaPareja++;

}

}

A partir de ese modelo, mediante clases hijas podemos ir definiendo cada tipo de dinosaurio, ya sí cada cual con sus propias características, como el tener plumas, cuernos, escamas, etcétera.

Y otro ejemplo más para que se termine de entender qué es la abstracción. En una cooperativa trabajan muchas personas. Unos se dedican a la contabilidad, otros al envío de productos, otros a fabricarlos... pero todos tienen una serie de características comunes, como el sueldo que reciben, la fecha en que se dieron de alta en la cooperativa, el ocuparse de algo. Todas esas características son las que podrían formar una clase abstracta en el programa de gestión del proyecto que luego se matizarían en las clases herederas en función de las peculiaridades de cada caso.

Bueno, espero que con estos ejemplos, más o menos, se entienda qué diantres significa eso de la abstracción y para qué sirve. Veamos ahora cómo funciona en PHP

Clases abstractas en PHP

Ya sabemos que las clases normales permiten ser heredadas y, al menos, cuentan con algún método público que permite acceder a la información para leerla o manipularla una vez creada una instancia. Una estructura tipo podría contar con un método constructor, otro con funciones getter y otro con funciones setter.

class clase_normal

{

protected $propiedad1;

public function __construct ($recoge) {

$this->propiedad1 = $recoge;

}

public function metodoSetter () {

$this->propiedad1 = $this->propiedad1 + 1;

return $this->propiedad1;

}

public function metodoGetter () {

return $this->propiedad1;

}

}

$nueva_instancia = new clase_normal (5);

echo $nueva_instancia ->metodoSetter();

Las clases abstractas funcionan de forma distinta. Para declararlas se antepone la palabra reservada abstract, tanto en la definición de la clase como de los métodos.

abstract class SoyUnaClaseAbstracta

{

abstract protected function soyUnMetodoAbstracto();

}

De las clases abstractas no se puede sacar ninguna instancia, es decir, no se puede definir ningún objeto directamente a partir de ellas. Dicho en código, esto no funciona.

abstract class SoyUnaClaseAbstracta

{

abstract protected function soyUnMetodoAbstracto();

public function soyUnMetodoPublico() {

echo "No funciona";

}

}

// Esto no se vale 😛

$mi_claseAbstracta = new SoyUnaClaseAbstracta();

$mi_claseAbstracta->soyUnMetodoPublico();

Esto es lógico, ya que carece de sentido instanciar una abstracción que no está relacionada con nada en concreto. ¿Para qué vamos a necesitar instanciar la interruptoridad o la dinosauriez? Lo que querremos usar es un submarino con un interruptor o un estegosaurio con ganas de reproducirse.

En cambio, claro está, sí que podemos instanciar todas las clases derivadas, herederas, de una clase abstracta.

Métodos abstractos

Una clase abstracta puede incluir métodos privados, protegidos y públicos, pero además estos métodos pueden declararse como abstractos. De hecho, toda clase que contenga al menos un método abstracto debe definirse abstracta, aunque una clase abstracta no necesita contener obligatoriamente un método abstracto.

Los métodos abstractos no se implementan,  es decir, no se desarrollan en la clase madre, sino en las clases hijas. Y esto es obligatorio: todo método abstracto de la clase madre debe recogerse en la clase hija.

Expresado en código, si intentamos hacer esto:

abstract class SoyUnaClaseAbstracta

{

abstract protected function soyUnMetodoAbstracto();

}

class hija extends SoyUnaClaseAbstracta

{

// No implementamos el método...

}

Nos dirá que «Fatal error: Class hija contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (SoyUnaClaseAbstracta::soyUnMetodoAbstracto)».

¿Y para qué diantres sirven entonces? muy sencillo, para que la jerarquía de clases sea más sólida, pues fuerzan a que las clases hijas se comporten de determinada manera. Por ejemplo, imaginemos que tenemos una clase abstracta que dibuja figuras. En la clase no están definidas ni qué figuras son ni en qué soporte ni con qué deben pintarse, pero sí que deben dibujarse a partir de los parámetros recibidos; pues ahí podría funcionar un método abstracto dibujar(), que ya en la clase hija rectángulo se definirá como trazar 4 lados, en la de triángulo, 3 lados, etcétera.

Importante: se puede modificar el tipo de acceso de un método abstracto cuando se implementa en la clase hija, pero no de forma más restrictiva. Es decir, se puede redefinir un método private como protected o public y uno protected como public, pero no al revés.

abstract class SoyUnaClaseAbstracta

{

abstract protected function soyUnMetodoAbstracto();

}

class hija extends SoyUnaClaseAbstracta

{

// Esto no funciona
private function soyUnMetodoAbstracto() {

}

// Esto sí funciona

public function soyUnMetodoAbstracto() {

}

}

Clases finales

En cierta manera, lo contrario de las clases abstractas son las clases finales, que no pueden ser heredadas. También se puede declarar final un método, en cuyo caso no puede sobrescribirse. Tanto las clases como los métodos se definen finales anteponiendo la palabra final.

final class SoyUnaClaseFinal

{

final protected function soyUnMetodoFinal() {

return "Jajajaja, nadie me puede redefinir y dominaré el mundo";

}

}

// Esto no funciona
class hija extends SoyUnaClaseFinal

{

// Y esto también daría error

function soyUnMetodoFinal() {

}

}

Bueno, pues por hoy ya está bien : )

|| Tags:

valoración de los lectores sobre PHP orientado a objetos 8: clases abstractas y finales

  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración negativa
  • 4.2 sobre 5 (26 votos)

¿Te ha parecido útil o interesante esta entrada?
dormido, valoración 1 nadapensativo, valoración 2 un poco sonrisa, valoración 3 a medias guiño, valoración 4 bastante aplauso, valoración 5 mucho

Tú opinión es muy importante, gracias por compartirla!

8 respuestas a “PHP orientado a objetos 8: clases abstractas y finales

  1. Luis Felipe el dijo:

    Gracias x tu articulo me ha servido para comprender lo abastracto de las clases acbastras jejeje, bueno suele confundirse tambien con las interfaces, seria genial una articulo con las diferencias entre interfaces y clases abstractas, gracias.

  2. gracias Luis. Las interfaces, básicamente, sirven para proyectos muy grandes. Son una especie de clases abstractas en las que los métodos declarados son de implementación obligatoria. La verdad es que no valen para mucho, pero sí, a ver si saco tiempo y preparo un post.