Diferencia entre revisiones de «Plantilla:PHP/Herencia»

De WikiEducator
Saltar a: navegación, buscar
(Herencia)
 
(33 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 me permite crear una jerarquía en los componentes software, que se pueden ir especializando
+
=== Herencia ===
Se puede definir una clase con ciertas características (atributos, métodos)
+
* La herencia es un mecanismo de programación que permite crear una jerarquía en los componentes ''software'', que se van especializando
*Posteriormente puedo definir otra clase a partir de la ya existente, quedándo implícitamente los atributos y métodos como también parte de su estructura o composición
+
* 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 (p.e Personas (médicos y bailarines) vehículos (Terrestres (coche, moto) Acuáticos (barco, lancha))
+
* 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]]
*Es una forma de obtener características comunes por separado y luego especializar evitando redundancias
 
*Facilita la reusabilidad y adaptación
 
*Vemos dos ejemplos  para explicar de forma empírica este concepto
 
{{MRM_Ejemplo|Title= Herencia: gestión personal ambulatorio|
 
*Se pide gestionar un ambulatorio.
 
*Para ello vamos a hacer sólo el diagrama de clases y su implementación.
 
*Lo hacemos a nivel básico (sin entrar en detalles).
 
*Tras realizar un 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 especifican
 
en los siguientes diagramas de clases
 
<gallery>
 
Image:claseConserje.png|Clase Conserje
 
Image:claseEnfermera.png|Clase Enfermera
 
Image:claseMedica.png|Clase Medicas
 
</gallery>
 
*Claramente vemos que todos ellos tienen varios elementos en común.
 
*Esto nos permite crear una clases genérica que por ejemplo podemos llamar '''''personalAmbulatorio'''''
 
*Posteriormente creamos una especialización de '''''personalAmbulatorio''''' con los elementos particulares
 
*El digrama podría quedar
 
[[Imagen:JerarquiaPersonaAmbulatorio.png|center|600px]]<br />
 
<font size<nowiki>=</nowiki>5 color<nowiki>=</nowiki>red>[[Usuario:ManuelRomero/ProgramacionWeb/php/POO/Herencia/EjemploAmbulatorio | Posible Solución]]</font>
 
<hr />
 
  
 +
* 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.
 +
[[Archivo:jerarquia_clases_1.png]]
 +
 +
{{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).
 
}}
 
}}
  
*Vamos a platear un ejemplo  
+
* Para establecer una jerarquía, usamos la palabra reservada '''extends''' en las clases que heredan. 
Vamos a suponer que queremos hacer un programa de figuras geométricas.
+
* Vamos a verlo con un ejemplo:
Tenemos cuadrados, rectángulos y triángulos.
+
[[Archivo:jerarquia_ambulatoria_1.png]]
[[Archivo:herenciaPHP1.png]]
+
 
 +
* Primero establecemos la clase '''Persona''':
  
Cómo vemos hay atributos comunes podríamos declara una clase común llamada Polígono con los elementos comunes y luego tres clases que deriven de '''''Poligono'''''
 
[[Archivo:herenciaPHP2.png]]
 
*La implementación de esta estructura podría quedar de la siguiente manera
 
 
<source lang=php>
 
<source lang=php>
 +
<?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;
 +
    }
 +
}
 +
?>
 
</source>
 
</source>
  
*Ahora vemos también un método común que es '''''calcularArea()'''''
+
* Ahora establecemos la clase que hereda de Persona:
*A pesar de que es común y la idea de la acción es igual, la implementación es diferente en cada caso
+
*Para estas situaciones está la posib
+
  
===Métodos abstractos===
+
{{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'''. 
*Son métodos que no tienen código
+
;En un momento dado, podemos invocar métodos del supertipo usando el operador '''parent''' junto con el operador de resolución de ámbito '''::'''.
*Sirven para estructurar nuestra clase
+
}}
{{MRM_Ejemplo|
+
 
*Definimos la clase polígono
+
<source lang=php>
*Es una estrucut
+
<?php
abstract class Poligono {
+
class Sanitario extends Persona {
    //put your code here
+
     protected $centroSalud;
   
+
     protected $yearTitulacion;
     protected $lados;
+
 
     protected $area;
+
     public function __construct(string $n, string $d, int $e, string $centro, int $year) {
   
+
        parent::__construct($n, $d, $e);
     public function __construct ($lados){
+
         $this->centroSalud = $centro;
         $this->lados = $lados;
+
        $this->yearTitulacion = $year;
 +
    }
 +
 
 +
    public function mostrarInfo(){
 +
        echo "$this->nombre trabaja en $this->centroSalud y obtuvo su título en $this->yearTitulacion.";
 
     }
 
     }
   
 
   
 
    abstract public function calculaArea();
 
               
 
       
 
 
}
 
}
 +
?>
 +
</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 />
 
}}
 
}}
  
 +
==== 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.
  
Puedo heredar un método y añadir cosas (MRM Falta ejemplo)
+
{{MRM_Ejemplo|Title=Clase abstracta|
-->
+
* Ejemplo ilustrativo:
 +
[[Archivo:claseAbstracta.png]]
 +
}}
  
<!-- Dejo esto aquí a ver si lo completo o no
+
* 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. 
===métodos abstractos===
+
* 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'''.
*Son métodos que no se implementan en una clase, si no en la clase que herede de ésta.
+
Las clases que contengan métodos abstractos no se pueden instanciar en memoria.
+
===métodos estáticos===
+
  
 +
{{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|
 +
;Nunca podremos instanciar un objeto de una clase abstracta.
 +
* Esto es lógico, ya que ese objeto no tendría instrucciones para ejecutar sus métodos abstractos.
 +
}}
  
 +
* Vamos a plantear un ejemplo práctico:
  
====Enlace estático en tiempo de ejecución====
+
{{MRM_Ejemplo|Title=App de Geometría|
*Para poder hacer referencia en tiempo de ejecución a un elemento estático de la clase se usa este operador
+
;Gestionar figuras geométricas de tipo triángulo, cuadrado y rectángulo. 
*Elementos estáticos en php
+
* De ellas queremos conocer:
#Constantes y Propiedades y métodos estáticas
+
# El número de lados. 
*Usaremos el operador '''''::''''' de resolución de ámbito
+
# Calcular el área. 
*Especificaremos el nombre de la clase del cual queremos acceder a su constante
+
# 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]]
  
#
+
* Definimos las siguientes clases:
*Usaremos igualmente el operador de resolución de ámbito '''''::'''''
+
  
#propiedades y métodos no estáticos
+
;Clase Polígono  
*Para ellos usaremos el operador '''''->''''', precedido de la seudovariable '''''$this'''''
+
<font size=5 color=red>[[Usuario:ManuelRomero/ProgramacionWeb/php/POO/Herencia/EjemploGeometria/Poligono | Descripción de la Clase Polígono]]</font>
==static==
+
==$this==
+
  
===métodos===
+
<hr />
===pseudovariables '''''this'''''===
+
===operador '''''self''''' y '''''parent'''''===
+
  
 +
;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 />
 +
 
 +
;Clase Cuadrado 
 +
<font size=5 color=red>[[Usuario:ManuelRomero/ProgramacionWeb/php/POO/Herencia/EjemploGeometria/Cuadrado | Descripción de la Clase Cuadrado]]</font>
 +
 
 +
<hr />
 +
 
 +
;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 />
 +
 
 +
;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>
 +
<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>
 +
 
 +
;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)  

Herencia.png

  • 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.

Jerarquia clases 1.png



Icon key points.gif

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.
  • Vamos a verlo con un ejemplo:

Jerarquia ambulatoria 1.png

  • 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:



Icon key points.gif

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 ::.



<?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.



Icon casestudy.gif
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:

  • 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í:

JerarquiaPersonaAmbulatorio.png


  • Ver la aplicación ejecutándose:

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.



Icon casestudy.gif
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.



Icon define.gif
Clase abstracta
  • Es aquella clase que tiene uno o más métodos abstractos.




Icon define.gif
Método abstracto
  • Es un método que no tiene código asociado.
  • Su implementación se realizará en las clases derivadas.




Icon key points.gif

Puntos clave

Nunca podremos instanciar un objeto de una clase abstracta.
  • Esto es lógico, ya que ese objeto no tendría instrucciones para ejecutar sus métodos abstractos.



  • Vamos a plantear un ejemplo práctico:



Icon casestudy.gif
App de Geometría
{{{1}}}