jairogarcíarincón
Cuando empezamos a profundizar en el uso de clases es cuando apreciamos la potencia de la programación orientada a objetos.
En este apartado vamos a ver cómo podemos mejorar nuestras clases para que sean mucho más versátiles y nos sirvan para más cosas, y para ello partiremos de los conceptos de herencia, extensión y polimorfismo.
Según el sitio oficial de PHP:
"La herencia es un principio de programación bien establecido y PHP hace uso de él en su modelado de objetos. Este principio afectará la manera en que muchas clases y objetos se relacionan unas con otras.
Por ejemplo, cuando se extiende una clase, la subclase hereda todos los métodos públicos y protegidos de la clase padre. A menos que una clase sobrescriba esos métodos, mantendrán su funcionalidad original.
Esto es útil para la definición y abstracción de la funcionalidad y permite la implementación de funcionalidad adicional en objetos similares sin la necesidad de reimplementar toda la funcionalidad compartida."
Dicho de otro modo, mediante el uso de la herencia vamos a poder cambiar la morfología de la clase, extendiéndola para adaptarla a uestras necesidades concretas.
Para verlo en forma de ejemplo, vamos a suponer en la siguiente ampliación para nuestro desarrollo de coches:
- Estaba pensado para la gestión de vehículos de un parking de 2 plantas subterráneas más una de superficie.
- Ahora se va a ampliar su uso a furgonetas y autobuses.
- Los autobuses no pueden aparcar en las plantas subterráneas pero sí en la superficie y además debo conocer el nombre de la empresa propietaria.
- Las furgonetas solo pueden aparcar en la primera planta subterránea o en superficie y además debo conocer la altura.
- Los coches solo pueden aparcar en las plantas subterráneas pero no en la superficie.
Una posible solución podría pasar por realizar las siguientes acciones:
- Modificar la clase Coche (y su archivo correspondiente) para que ahora se llame Vehículo.
- Añadir el atributo planta y sus correspondientes get() y set() para hacer referencia a la planta en la que estaciona el vehículo (aunque no aparezca en el constructor al no saber en qué planta estará el coche).
- Añadir los atributos planta y plantas con un array que incluya las diferentes plantas disponibles.
- Crear las clases Autobus, Furgoneta y Coche que extiendan la clase Vehiculo e incorporen el método puedeAparcar() para comprobar si puede o no puede aparcar, en función de la planta de entrada (este método se llamará igual pero será diferente en cada clase).
- Añadir a la clase Autobus el atributo empresa y sobre-escribir el constructor para que incluya dicho atributo.
La clase Vehiculo.php:
<?php
class Vehiculo
{
//Variables o atributos
var $marca;
var $modelo;
var $color;
var $propietario;
var $planta;
var $plantas = array("superficie","subterraneo1","subterraneo2");
function __construct($miMarca,$miModelo,$miColor,$miPropietario){
$this->marca = $miMarca;
$this->modelo = $miModelo;
$this->color = $miColor;
$this->propietario = $miPropietario;
}
//Funciones o métodos
function setMarca($miMarca){
$this->marca = $miMarca;
}
function getMarca(){
return $this->marca;
}
function setModelo($miModelo){
$this->modelo = $miModelo;
}
function getModelo(){
return $this->modelo;
}
function setColor($miColor){
$this->color = $miColor;
}
function getColor(){
return $this->color;
}
function setPropietario($miPropietario){
$this->propietario = $miPropietario;
}
function getPropietario(){
return $this->propietario;
}
function setPlanta($miPlanta){
$this->planta = $miPlanta;
}
function getPlanta(){
return $this->planta;
}
}
La clase Autobus.php:
<?php
//Requiero el archivo de clase para extenderlo en este script
require_once("Vehiculo.php");
class Autobus extends Vehiculo
{
var $empresa;
function __construct($miMarca,$miModelo,$miColor,$miPropietario,$miEmpresa){
$this->marca = $miMarca;
$this->modelo = $miModelo;
$this->color = $miColor;
$this->propietario = $miPropietario;
$this->empresa = $miEmpresa;
}
//Funciones o métodos
function setEmpresa($miEmpresa){
$this->empresa = $miEmpresa;
}
function getEmpresa(){
return $this->empresa;
}
function puedeAparcar($miPlanta){
//True si está en el array y es superficie
return (array_search($miPlanta,$this->plantas) !== false && array_search($miPlanta,$this->plantas) == 0);
}
}
La clase Furgoneta.php:
<?php
//Requiero el archivo de clase para extenderlo en este script
require_once("Vehiculo.php");
class Furgoneta extends Vehiculo
{
function puedeAparcar($miPlanta){
//True si está en el array y no es subterraneo2
return (array_search($miPlanta,$this->plantas) !== false && array_search($miPlanta,$this->plantas) < 2);
}
}
La clase Coche.php:
<?php
//Requiero el archivo de clase para extenderlo en este script
require_once("Vehiculo.php");
class Coche extends Vehiculo
{
function puedeAparcar($miPlanta){
//True si está en el array y no es superficie
return (array_search($miPlanta,$this->plantas) !== false && array_search($miPlanta,$this->plantas) > 0);
}
}
El archivo index.php:
<?php
//Requiero los archivos de clase para incluirlos en este script
require("Autobus.php");
require("Furgoneta.php");
require("Coche.php");
?>
<h1>Ejemplo 4: Herencia, Extensión y Polimorfismo</h1>
<?php
//Instancio y configuro los vehículos
$autobus = new Autobus("Volvo","9800 2017","gris","Mario","Desfufor");
$furgoneta = new Furgoneta("Wolkswagen","Caravelle","blanco","Rebeca");
$coche = new Coche("Toyota","Corolla","verde","Marcos");
?>
<div>
¿Puedo aparcar el coche en la superficie?:
<strong><?php echo ($coche->puedeAparcar("superficie")) ? "si" : "no" ?></strong>
</div>
<div>
¿Puedo aparcar el coche en el subterráneo 2?:
<strong><?php echo ($coche->puedeAparcar("subterraneo2")) ? "si" : "no" ?></strong>
</div>
<div>
¿Puedo aparcar la furgoneta en la superficie?:
<strong><?php echo ($furgoneta->puedeAparcar("superficie")) ? "si" : "no" ?></strong>
</div>
<div>
¿Puedo aparcar la furgoneta el subterráneo 2?:
<strong><?php echo ($furgoneta->puedeAparcar("subterraneo2")) ? "si" : "no" ?></strong>
</div>
<div>
¿Puedo aparcar el autobús en la superficie?:
<strong><?php echo ($autobus->puedeAparcar("superficie")) ? "si" : "no" ?></strong>
</div>
<div>
¿Puedo aparcar el autobús el subterráneo 1?:
<strong><?php echo ($autobus->puedeAparcar("subterraneo1")) ? "si" : "no" ?></strong>
</div>
<div>
¿A qué empresa pertenece el autobús?:
<strong><?php echo $autobus->getEmpresa() ?></strong>
</div>
Y como siempre, vamos a analizar qué conclusiones podríamos extraer del ejemplo anterior:
- Para extender una clase y poder acceder a todos sus métodos y atributos, tan solo tenemos que utilizar la directiva extends después del nombre de clase y añadir el nombre de la clase principal.
- Los nombres de clases, variables o funciones nunca llevan tildes, caracteres extraños ni espacios, y no pueden empezar por un número.
- No todos los atributos deben estar en el constructor, solo los necesarios para inicializar correctamente el objeto de clase.
- Es posible sobre-escribir un atributo o método (incluyendo el constructor) en la clase secundaria simplemente declarándolo de nuevo en ella.
- Al usar varias clases que extienden de la misma, es mejor utilizar require_once() para evitarnos la carga de la clase principal de nuevo.
- A la hora de mezclar PHP con HTML, es mejor y más seguro frente a posibles inyecciones de código de tipo XSS incrustar el PHP dentro del HTML, esto es, abrir y cerrar las etiquetas de PHP en vez de hacer echos par el HTML.
- Para PHP en una comparación, 0 y false es el mismo valor, lo que puede dar lugar a confusión.
Ejercicio propuesto 4
- Modifica el Ejercicio 3 para poder realizar la gestión de contactos de un colegio.
- Los alumnos deberán tener el atributo curso y un array de asignaturas (no todos las mismas) con sus métodos correspondientes.
- Los profesores deberán tener los atributos salario y asignatura con sus métodos correspondientes.
- El personal deberá tener el atributo salario con sus métodos correspondientes.
- Realiza diferentes comprobaciones para ver si un alumno tiene cierta asignatura o no, o si un profesor gana más que otro o más que alguien del personal, o cómo el alumno a partir de una asignatura puede averiguar quién es su profesor.
Publicado el 21 de Noviembre de 2024