Diferencia entre revisiones de «Plantilla:PHP/Herencia»
De WikiEducator
| (27 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. |
| − | *Vemos dos ejemplos | + | * Facilita la reutilización y la adaptación del código. |
| − | {{MRM_Ejemplo|Title= Herencia: gestión personal ambulatorio| | + | |
| − | *Se pide gestionar un ambulatorio. | + | ;La herencia implica declarar jerarquías de clases |
| − | *Para ello | + | * 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]] | |
| − | *Tras realizar | + | |
| − | + | {{MRM_Puntos clave| | |
| − | + | :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 '''extends''' en las clases que heredan. | |
| − | Las propiedades (atributos) y métodos de cada clase se | + | * Vamos a verlo con un ejemplo: |
| − | + | [[Archivo:jerarquia_ambulatoria_1.png]] | |
| − | + | ||
| − | + | * Primero establecemos la clase '''Persona''': | |
| − | + | ||
| − | + | <source lang=php> | |
| − | + | <?php | |
| − | *Claramente vemos que todos ellos | + | class Persona { |
| − | *Esto nos permite crear una | + | protected $nombre; |
| − | *Posteriormente | + | 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; | ||
| + | } | ||
| + | } | ||
| + | ?> | ||
| + | </source> | ||
| + | |||
| + | * Ahora establecemos la clase que hereda de Persona: | ||
| + | |||
| + | {{MRM_Puntos clave|Title=Principios del uso de la herencia| | ||
| + | ;Todos los atributos y métodos públicos y protegidos del supertipo '''Persona''' son también de '''Sanitario'''. | ||
| + | ;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> | ||
| + | <?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."; | ||
| + | } | ||
| + | } | ||
| + | ?> | ||
| + | </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| | ||
| + | <source lang=php> | ||
| + | <?php | ||
| + | spl_autoload_register(function ($nombre_clase) { | ||
| + | include $nombre_clase . '.php'; | ||
| + | }); | ||
| + | |||
| + | $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"); | ||
| + | $medico3 = new Medica("Nieves", "Ruiz", "Casa de Nieves", 44, "Dermatología"); | ||
| + | $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", "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"); | ||
| + | ?> | ||
| + | <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> | ||
| + | </source> | ||
| + | }} | ||
<hr /> | <hr /> | ||
}} | }} | ||
| − | ==== | + | |
| − | + | ==== Clases Abstractas ==== | |
| − | *Cuando realizamos jerarquías muchas veces encontramos métodos comunes a varias clases. Esto implicaría que ese método | + | * Cuando realizamos jerarquías, muchas veces encontramos métodos comunes a varias clases. |
| − | *Pero puede ocurrir que aunque el concepto del método | + | 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_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. |
| − | * | + | |
| − | ;Clase Polígono | + | [[Archivo:app_geometria.png]] |
| − | + | ||
| − | <font size | + | * Definimos las siguientes clases: |
| + | |||
| + | ;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 /> | ||
| − | ;Clase Rectángulo | + | |
| − | <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 Cuadrado | + | |
| − | <font size | + | ;Clase Cuadrado |
| + | <font size=5 color=red>[[Usuario:ManuelRomero/ProgramacionWeb/php/POO/Herencia/EjemploGeometria/Cuadrado | Descripción de la Clase Cuadrado]]</font> | ||
| + | |||
<hr /> | <hr /> | ||
| − | ;Clase | + | ;Clase Triángulo |
| − | <font size | + | <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 | + | |
| + | ;Uso de esta aplicación | ||
| + | * Un posible archivo '''index.php''' que crea los objetos, calcula sus áreas y los dibuja: | ||
| + | |||
<source lang=php> | <source lang=php> | ||
| + | <!DOCTYPE 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> | ||
</source> | </source> | ||
| − | ;Resultado de su ejecución | + | |
| − | [[Archivo: | + | ;Resultado de su ejecución |
| + | [[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:


