Diferencia entre revisiones de «Plantilla:PHP/Herencia»
De WikiEducator
(→Herencia) |
|||
| (5 revisiones intermedias por el mismo usuario no mostrado) | |||
| Línea 1: | Línea 1: | ||
| − | ===Herencia=== | + | <div id=parrafo> |
| − | *La herencia es un mecanismo de programación que | + | === Herencia === |
| − | + | * La herencia es un mecanismo de programación que permite crear una jerarquía en los componentes ''software'', que se van especializando. | |
| − | + | * Es un principio de abstracción mediante el cual podemos crear una jerarquía de clases, con una raíz que contiene los elementos comunes y nodos que representan clases especializadas. | |
| − | *Es una característica muy natural | + | * La idea es definir una clase con ciertas características comunes (atributos, métodos). Posteriormente, crearemos otras clases a partir de la ya existente, heredando implícitamente los atributos y métodos como parte de su estructura o composición. |
| + | |||
| + | * Es una característica muy natural. Por ejemplo: | ||
| + | - Personas → (Médicos, Bailarines) | ||
| + | - Vehículos → (Terrestres → Coche, Moto) / (Acuáticos → Barco, Lancha) | ||
| + | |||
[[Archivo:Herencia.png]] | [[Archivo:Herencia.png]] | ||
| − | * | + | |
| − | *Facilita la | + | * La herencia es una forma de obtener características comunes por separado y luego especializarlas, evitando redundancias. |
| − | ;La | + | * Facilita la reutilización y la adaptación del código. |
| − | *En la raíz de la | + | |
| − | [[Archivo: | + | ;La herencia implica declarar jerarquías de clases |
| + | * En la raíz de la jerarquía establecemos la parte o estructura común a todas las clases, y posteriormente vamos especializando las diferencias de cada una. | ||
| + | [[Archivo:jerarquia_clases_1.png]] | ||
{{MRM_Puntos clave| | {{MRM_Puntos clave| | ||
| − | :Todos los atributos y métodos de | + | :Todos los atributos y métodos de una clase superior (supertipo) que sean públicos o '''protegidos''' son heredados por todas las clases derivadas (subtipos). |
}} | }} | ||
| − | *Para establecer una jerarquía, usamos la palabra reservada | + | |
| − | *Vamos a verlo con un ejemplo | + | * Para establecer una jerarquía, usamos la palabra reservada '''extends''' en las clases que heredan. |
| + | * Vamos a verlo con un ejemplo: | ||
[[Archivo:jerarquia_ambulatoria_1.png]] | [[Archivo:jerarquia_ambulatoria_1.png]] | ||
| − | |||
| − | |||
| − | |||
| + | * Primero establecemos la clase '''Persona''': | ||
| − | class Persona | + | <source lang=php> |
| − | { | + | <?php |
| + | class Persona { | ||
protected $nombre; | protected $nombre; | ||
protected $direccion; | protected $direccion; | ||
| Línea 29: | Línea 36: | ||
protected $frase; | protected $frase; | ||
| − | public function __construct(string $n, string $d, | + | public function __construct(string $n, string $d, int $e){ |
| − | + | $this->nombre = $n; | |
| + | $this->direccion = $d; | ||
| + | $this->edad = $e; | ||
} | } | ||
| − | public | + | public function establecer_frase(string $frase){ |
| − | + | $this->frase = $frase; | |
} | } | ||
| − | public function hablar ( | + | public function hablar(){ |
| − | + | echo $this->frase; | |
} | } | ||
| − | |||
} | } | ||
| − | + | ?> | |
</source> | </source> | ||
| − | *Ahora establecemos la clase que hereda de | + | * Ahora establecemos la clase que hereda de Persona: |
| + | |||
{{MRM_Puntos clave|Title=Principios del uso de la herencia| | {{MRM_Puntos clave|Title=Principios del uso de la herencia| | ||
| − | ;Todos los atributos y métodos públicos y protegidos del supertipo | + | ;Todos los atributos y métodos públicos y protegidos del supertipo '''Persona''' son también de '''Sanitario'''. |
| − | ;En un momento dado, podemos invocar | + | ;En un momento dado, podemos invocar métodos del supertipo usando el operador '''parent''' junto con el operador de resolución de ámbito '''::'''. |
}} | }} | ||
| − | + | ||
<source lang=php> | <source lang=php> | ||
<?php | <?php | ||
| − | + | class Sanitario extends Persona { | |
| − | class Sanitario extends Persona | + | |
| − | { | + | |
protected $centroSalud; | protected $centroSalud; | ||
protected $yearTitulacion; | protected $yearTitulacion; | ||
| − | public function __construct(string $ | + | public function __construct(string $n, string $d, int $e, string $centro, int $year) { |
| − | parent::__construct(); | + | parent::__construct($n, $d, $e); |
| − | + | $this->centroSalud = $centro; | |
| + | $this->yearTitulacion = $year; | ||
| + | } | ||
| + | public function mostrarInfo(){ | ||
| + | echo "$this->nombre trabaja en $this->centroSalud y obtuvo su título en $this->yearTitulacion."; | ||
} | } | ||
| + | } | ||
| + | ?> | ||
| + | </source> | ||
| + | --- | ||
| − | </ | + | * Vemos dos ejemplos para explicar de forma práctica este concepto. |
| + | |||
| + | {{MRM_Ejemplo|Title=Herencia: gestión de personal en un ambulatorio| | ||
| + | * Se pide gestionar un ambulatorio. | ||
| + | * Para ello haremos solo el diagrama de clases y su implementación a nivel básico (sin entrar en detalles). | ||
| + | * Tras realizar el análisis, se determina que se pretende gestionar los datos de los empleados y anotar las acciones básicas que realizan. | ||
| + | |||
| + | ;Encontramos los siguientes elementos, que especificamos como clases: | ||
| + | * Conserjes | ||
| + | * Enfermeras | ||
| + | * Médicas | ||
| + | |||
| + | Las propiedades (atributos) y métodos de cada clase se representan en los siguientes diagramas: | ||
| + | <gallery> | ||
| + | Image:claseConserje.png|Clase Conserje | ||
| + | Image:claseEnfermera.png|Clase Enfermera | ||
| + | Image:claseMedica.png|Clase Médica | ||
| + | </gallery> | ||
| + | |||
| + | * Claramente vemos que todos ellos comparten varios elementos comunes. | ||
| + | * Esto nos permite crear una clase genérica, por ejemplo '''personalAmbulatorio'''. | ||
| + | * Posteriormente crearemos especializaciones de esta clase con los elementos particulares. | ||
| + | |||
| + | El diagrama podría quedar así: | ||
| + | [[Archivo:JerarquiaPersonaAmbulatorio.png|center|400px]] | ||
| + | <br /> | ||
| + | * Ver la aplicación ejecutándose: | ||
| + | http://manuel.infenlaces.com/dwes/ejercicios/T6_Ambulatorio/ | ||
| − | + | {{Plegable|hide|Posible index de uso| | |
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | {{Plegable|hide|Posible index de uso | | + | |
<source lang=php> | <source lang=php> | ||
<?php | <?php | ||
| Línea 101: | Línea 118: | ||
}); | }); | ||
| − | $medico1 = new Medica("María", "Martínez", "Casa de María", 29, " | + | $medico1 = new Medica("María", "Martínez", "Casa de María", 29, "Cardiología"); |
$medico2 = new Medica("Luis", "Pérez", "Casa de Luis", 38, "Pediatría"); | $medico2 = new Medica("Luis", "Pérez", "Casa de Luis", 38, "Pediatría"); | ||
$medico3 = new Medica("Nieves", "Ruiz", "Casa de Nieves", 44, "Dermatología"); | $medico3 = new Medica("Nieves", "Ruiz", "Casa de Nieves", 44, "Dermatología"); | ||
$conserje = new Conserje("Soledad", "Viruela", "Casa de Soledad", 58, "Mostrador Entrada"); | $conserje = new Conserje("Soledad", "Viruela", "Casa de Soledad", 58, "Mostrador Entrada"); | ||
| − | $ | + | $enfermera1 = new Enfermera("Javier", "Moreno", "Casa de Javier", "General", 1990); |
| − | $enfermera2 = new Enfermera("Luis", " | + | $enfermera2 = new Enfermera("Luis", "Pérez", "Casa de Javier", "General", 1990); |
| + | $conserje->avisoEnfermera($enfermera1, "Realizar cura en brazo del Sr. Martínez NSS 50/2155441/35"); | ||
| + | $enfermera1->avisoMedico($medico3, "Paciente con tos y fiebre"); | ||
| − | $ | + | $enfermera2->avisoMedico($medico2, "Paciente con fiebre y vómitos"); |
| + | $enfermera2->avisoMedico($medico3, "Paciente con pie torcido; posible fractura"); | ||
| − | + | $conserje->avisoMedico($medico1, "Visitar en casa por fiebre alta", "Visita"); | |
| − | + | $conserje->avisoMedico($medico2, "Persona mayor con poca movilidad", "Visita"); | |
| − | + | $conserje->avisoMedico($medico3, "Niño pequeño con fiebre", "Consulta"); | |
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | $conserje->avisoMedico($medico1, "Visitar en casa | + | |
| − | + | ||
| − | + | ||
| − | $conserje->avisoMedico($medico2, "Persona mayor con poca | + | |
| − | $conserje->avisoMedico($medico3, "Niño pequeño con fiebre | + | |
| − | + | ||
?> | ?> | ||
| − | |||
<html> | <html> | ||
| − | + | <head> | |
| − | + | <meta charset="UTF-8"> | |
| − | + | <title>Gestión Ambulatorio</title> | |
| − | + | <link rel="stylesheet" href="./stilo.css" type="text/css"/> | |
| − | + | </head> | |
| − | + | <body> | |
| − | + | <?php | |
| − | + | echo $medico3; | |
| − | + | echo $medico1; | |
| − | + | echo $medico2; | |
| − | + | ?> | |
| − | + | </body> | |
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
</html> | </html> | ||
</source> | </source> | ||
| + | }} | ||
| + | <hr /> | ||
| + | }} | ||
| + | ==== Clases Abstractas ==== | ||
| + | * Cuando realizamos jerarquías, muchas veces encontramos métodos comunes a varias clases. | ||
| + | Esto implicaría que ese método debería pertenecer a una superclase (o clase padre), de la que luego se heredará. | ||
| + | * Pero puede ocurrir que, aunque el concepto del método sea común a todas las clases, la forma de implementarlo sea diferente en cada una. | ||
| + | |||
| + | {{MRM_Ejemplo|Title=Clase abstracta| | ||
| + | * Ejemplo ilustrativo: | ||
| + | [[Archivo:claseAbstracta.png]] | ||
}} | }} | ||
| − | + | * En este caso, la forma correcta de proceder es especificar el método en la clase superior y dejar su implementación a las clases derivadas. | |
| − | + | * El método especificado en la clase superior será un método sin código, conocido como '''método abstracto''', y la clase donde se define pasa a ser una '''clase abstracta'''. | |
| − | + | ||
| − | + | {{MRM_Definicion|Title=Clase abstracta| | |
| + | * Es aquella clase que tiene uno o más métodos abstractos. | ||
}} | }} | ||
| − | + | ||
| − | + | {{MRM_Definicion|Title=Método abstracto| | |
| − | + | * Es un método que no tiene código asociado. | |
| − | + | * Su implementación se realizará en las clases derivadas. | |
| − | + | ||
| − | + | ||
| − | {{MRM_Definicion|Title= | + | |
| − | + | ||
| − | + | ||
| − | *Es un método que no tiene código asociado | + | |
| − | * | + | |
}} | }} | ||
| + | |||
{{MRM_Puntos clave| | {{MRM_Puntos clave| | ||
| − | ;Nunca podremos instanciar un objeto de una clase abstracta | + | ;Nunca podremos instanciar un objeto de una clase abstracta. |
| − | *Esto es | + | * Esto es lógico, ya que ese objeto no tendría instrucciones para ejecutar sus métodos abstractos. |
}} | }} | ||
| − | *Vamos a | + | * Vamos a plantear un ejemplo práctico: |
{{MRM_Ejemplo|Title=App de Geometría| | {{MRM_Ejemplo|Title=App de Geometría| | ||
| − | ;Gestionar figuras geométricas de tipo triángulo, cuadrado y | + | ;Gestionar figuras geométricas de tipo triángulo, cuadrado y rectángulo. |
| − | *De ellas queremos conocer: | + | * De ellas queremos conocer: |
| − | # | + | # El número de lados. |
| − | # | + | # Calcular el área. |
| − | # | + | # Dibujar el polígono (usaremos un pequeño código JavaScript para el ''canvas''). |
| − | # | + | # Conocer el número de lados del polígono. |
| + | |||
[[Archivo:app_geometria.png]] | [[Archivo:app_geometria.png]] | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | * Definimos las siguientes clases: | |
| − | Descripción de la Clase | + | ;Clase Polígono |
| + | <font size=5 color=red>[[Usuario:ManuelRomero/ProgramacionWeb/php/POO/Herencia/EjemploGeometria/Poligono | Descripción de la Clase Polígono]]</font> | ||
<hr /> | <hr /> | ||
| − | |||
| − | <font size | + | ;Clase Rectángulo |
| + | <font size=5 color=red>[[Usuario:ManuelRomero/ProgramacionWeb/php/POO/Herencia/EjemploGeometria/Rectangulo | Descripción de la Clase Rectángulo]]</font> | ||
| − | |||
<hr /> | <hr /> | ||
| − | ;Clase | + | ;Clase Cuadrado |
| + | <font size=5 color=red>[[Usuario:ManuelRomero/ProgramacionWeb/php/POO/Herencia/EjemploGeometria/Cuadrado | Descripción de la Clase Cuadrado]]</font> | ||
| + | <hr /> | ||
| − | <font size | + | ;Clase Triángulo |
| + | <font size=5 color=red>[[Usuario:ManuelRomero/ProgramacionWeb/php/POO/Herencia/EjemploGeometria/Triangulo | Descripción de la Clase Triángulo]]</font> | ||
| − | |||
<hr /> | <hr /> | ||
| − | |||
| − | |||
| − | |||
| + | ;Uso de esta aplicación | ||
| + | * Un posible archivo '''index.php''' que crea los objetos, calcula sus áreas y los dibuja: | ||
| + | |||
| + | <source lang=php> | ||
<!DOCTYPE html> | <!DOCTYPE html> | ||
<html> | <html> | ||
| − | + | <head> | |
| − | + | <meta charset="UTF-8"> | |
| − | + | <title>App Geometría</title> | |
| − | + | </head> | |
| − | + | <body> | |
| − | + | <?php | |
| − | + | spl_autoload_register(function ($clase){ | |
| − | + | require "$clase.php"; | |
| − | + | }); | |
| − | + | ||
| − | + | $triangulo = new Triangulo(200, 300); | |
| − | + | $cuadrado = new Cuadrado(200); | |
| − | + | $rectangulo = new Rectangulo(200, 100); | |
| − | + | ||
| − | + | echo "<h4>Triángulo, " . Poligono::lados($triangulo) . | |
| − | + | " lados, área: " . $triangulo->area() . " px<sup>2</sup></h4>"; | |
| − | + | ||
| − | + | echo "<h4>Cuadrado, " . Poligono::lados($cuadrado) . | |
| − | + | " lados, área: " . $cuadrado->area() . " px<sup>2</sup></h4>"; | |
| − | + | ||
| − | + | echo "<h4>Rectángulo, " . Poligono::lados($rectangulo) . | |
| − | + | " lados, área: " . $rectangulo->area() . " px<sup>2</sup></h4>"; | |
| − | + | ||
| − | + | echo $triangulo->dibuja(); | |
| − | + | echo $cuadrado->dibuja(); | |
| − | + | echo $rectangulo->dibuja(); | |
| − | + | ?> | |
| − | + | </body> | |
| − | + | ||
</html> | </html> | ||
</source> | </source> | ||
| − | ;Resultado de su ejecución | + | |
| + | ;Resultado de su ejecución | ||
[[Archivo:AppGeometria.png]] | [[Archivo:AppGeometria.png]] | ||
}} | }} | ||
| − | + | </div> | |
Última revisión de 05:51 7 nov 2025
Herencia
- La herencia es un mecanismo de programación que permite crear una jerarquía en los componentes software, que se van especializando.
- Es un principio de abstracción mediante el cual podemos crear una jerarquía de clases, con una raíz que contiene los elementos comunes y nodos que representan clases especializadas.
- La idea es definir una clase con ciertas características comunes (atributos, métodos). Posteriormente, crearemos otras clases a partir de la ya existente, heredando implícitamente los atributos y métodos como parte de su estructura o composición.
- Es una característica muy natural. Por ejemplo:
- Personas → (Médicos, Bailarines) - Vehículos → (Terrestres → Coche, Moto) / (Acuáticos → Barco, Lancha)
- La herencia es una forma de obtener características comunes por separado y luego especializarlas, evitando redundancias.
- Facilita la reutilización y la adaptación del código.
- La herencia implica declarar jerarquías de clases
- En la raíz de la jerarquía establecemos la parte o estructura común a todas las clases, y posteriormente vamos especializando las diferencias de cada una.
|
- Para establecer una jerarquía, usamos la palabra reservada extends en las clases que heredan.
- Vamos a verlo con un ejemplo:
- Primero establecemos la clase Persona:
<?php class Persona { protected $nombre; protected $direccion; protected $edad; protected $frase; public function __construct(string $n, string $d, int $e){ $this->nombre = $n; $this->direccion = $d; $this->edad = $e; } public function establecer_frase(string $frase){ $this->frase = $frase; } public function hablar(){ echo $this->frase; } } ?>
- Ahora establecemos la clase que hereda de Persona:
|
<?php class Sanitario extends Persona { protected $centroSalud; protected $yearTitulacion; public function __construct(string $n, string $d, int $e, string $centro, int $year) { parent::__construct($n, $d, $e); $this->centroSalud = $centro; $this->yearTitulacion = $year; } public function mostrarInfo(){ echo "$this->nombre trabaja en $this->centroSalud y obtuvo su título en $this->yearTitulacion."; } } ?>
---
- Vemos dos ejemplos para explicar de forma práctica este concepto.
Herencia: gestión de personal en un ambulatorio
| |||
Las propiedades (atributos) y métodos de cada clase se representan en los siguientes diagramas:
El diagrama podría quedar así:
http://manuel.infenlaces.com/dwes/ejercicios/T6_Ambulatorio/
|
Clases Abstractas
- Cuando realizamos jerarquías, muchas veces encontramos métodos comunes a varias clases.
Esto implicaría que ese método debería pertenecer a una superclase (o clase padre), de la que luego se heredará.
- Pero puede ocurrir que, aunque el concepto del método sea común a todas las clases, la forma de implementarlo sea diferente en cada una.
Clase abstracta
| |
|
- En este caso, la forma correcta de proceder es especificar el método en la clase superior y dejar su implementación a las clases derivadas.
- El método especificado en la clase superior será un método sin código, conocido como método abstracto, y la clase donde se define pasa a ser una clase abstracta.
|
|
- Vamos a plantear un ejemplo práctico:


