Diferencia entre revisiones de «Usuario:ManuelRomero/ProgramacionWeb/Objetos/introduccionBase»

De WikiEducator
Saltar a: navegación, buscar
 
Línea 7: Línea 7:
 
{{PHP/SintasixPHPOOPBase}}
 
{{PHP/SintasixPHPOOPBase}}
  
{{PHP/SobrecargaBase}}
+
{{PHP/Sobrecarga}}
  
{{PHP/EstaticoBase}}
+
{{PHP/Estatico}}
  
{{PHP/HerenciaBase}}
+
{{PHP/Herencia}}
  
 
</div>
 
</div>

Última revisión de 05:13 6 nov 2025



|}

Conceptos básicos de OOP

OOP Vs Programación estructurada

  • En programación el paradigma imperativo está basado en funciones y datos.
  • El paradigma orientado a objetos está basado en Objetos.
  • Los objetos son el elemento básico y central de la programación orientada a objetos (OOP) o (POO).
  • Podemos hablar de universo de discurso como el sistema que queremos automatizar por software
  • Un Objeto es una entidad (concreta o abstracta) que presenta una actividad en un entorno concreto, en un determinado universo de discurso.




Icon define.gif
Definición
Objeto Cada elemento activo que identificamos dentro de un determinado universo de discurso.
Serán nuestros componentes software para ensamblar nuestros programas




Icon casestudy.gif
Ejemplo
En un banco hay cuentas bancarias (objeto)
Las cuentas bancarias se identifican con un número y un titular (nombre, apellido y dni) atributos
Las cuentas se pueden dar de alta, de baja, hacer extracciones e ingresos y transferencias... métodos




Icon casestudy.gif
Ejemplo
En la gestión de una empresa, a nivel de información tenemos
  • Empleados
  • Nóminas
  • Base de datos
  • Proveedores
  • Facturas
  • Pedidos

UNIVERSO DISCUROS OBJETOS.png




Icon casestudy.gif

Fecha

Una fecha es un componente que tiene
  • Unos atributos que lo definen (dia,mes,año)
  • Podemos Validar una fecha, mostrar una fecha, sumar a una fecha un número de días, ... métodos
UNIVERSO DISCUROS OBJETOS.png
{{{1}}}



Icon casestudy.gif
Compartiva con la aplicación de master mind
Comparativa oo estructurado.png





  • Puede parecer una forma más complicada de programar, pero es una manera de dividir la naturaleza del problema que estamos estudiando en unidades independientes que pueden interactuar entre ellas.
  • Cada una de ellas va a tener una identidad propia asignando valores a sus atributos
  • Cada una de ellas va a tener un comportamiento concreto que va a ser lo que sabe hacer para que los demás o el programa principal lo utilice


Elementos en la programación orientada a objetos

  • De lo dicho anteriormente deducimos que tenemos dos elementos:
  1. Los atributos o características de la clase.
  2. Los métodos o comportamiento de la clase .
  • Para crear objetos, previamente hay que definir su estructura.
  • La definición de la estructura (atributos y métodos ) de componentes software se llama clase


Icon define.gif
Clase
La descripción y especificación de componentes software para su posterior uso en los programas
  • Una clase es la estructura de un tipo concreto de objetos.
  • Los objetos son elementos concretos en mi sistema. Instancias de la clase en memoria para ser usadas por un programa



Elementos de la POO


Icon define.gif
Atributo
  • Son las características o datos de un objeto.
  • Sus valores nos da el estado de un objeto en un momento dado.
  • Normalmente al instanciar un objeto en memoria lo primero que hacemos es dar valores a sus atributos
  • Es recomendado que los atributos estén encapsulados solo al objeto (privados)




Elementos de la POO


Icon define.gif
Métodos
  • Especifican el comportamiento de los objetos.
  • Permiten modificar y conocer el estado de un objetos (métodos getter and setter).
  • Permiten que un objeto haga cosas en el sistema (comunicación entre objetos) .
  • Los métodos son las acciones que el objeto sabe hacer, servicios que ofrece
  • También son las acciones internas para facilitar las acciones al objeto


Clase.png



OOP en PHP

  • PHP no se diseñó originalmente como un lenguaje orientado a objetos, por lo que muchas de las características de este paradigma se han ido incorporando en las últimas versiones, especialmente a partir de la versión 5.3.
  • PHP almacena el valor de un objeto como una referencia (dirección de memoria), no como una copia del valor.
  • Esto implica que, si queremos pasar un objeto a través de la red, debemos serializarlo, para que viaje también el valor del mismo y no solo la dirección de memoria (que en destino carecería de sentido). Veremos este concepto más adelante.
En PHP las clases tienen métodos y propiedades
  1. Propiedades: son los atributos o características de la clase.
  2. Métodos: representan el comportamiento de la clase.
Definir una clase en PHP
class NombreClase {
    // propiedades
    // métodos
}
  • NombreClase es un identificador válido según la siguiente expresión regular:
^[a-zA-Z_][a-zA-Z0-9_]*$
  • Se recomienda que el nombre de las clases comience con mayúscula.
  • Los nombres de las clases no son sensibles a mayúsculas/minúsculas, aunque es buena práctica tratarlos como si lo fueran.
  • Es muy recomendable guardar las clases en ficheros cuyo nombre coincida con el de la clase; esto permite la autocarga y forma parte de las buenas prácticas de programación.



Icon casestudy.gif
Ejemplo

Vamos a crear una clase llamada Fecha.

  • Atributos de la clase: dia, mes, year.
  • Método verFecha(): obtiene la fecha como una cadena de caracteres.
  • Método validarFecha(): verifica si una fecha es correcta o no.



Declaramos la clase

  • Utilizaremos siempre un fichero con el mismo nombre que la clase.
class Fecha {
 
}

Los atributos

  • Al declarar los atributos, aparece un concepto importante: la visibilidad o alcance del atributo, es decir, desde dónde puede verse o modificarse su valor.
Encapsulación
acceso a los componentes
  • Al definir tanto las propiedades como los métodos, especificamos su nivel de acceso.
  • Es una buena práctica no permitir acceso directo a los atributos, sino hacerlo a través de métodos específicos.



Icon key points.gif

Puntos clave

  • La encapsulación es uno de los pilares de la POO.
Permite o restringe la visibilidad de los componentes de una clase.



Visibilidad
  • Implementa el principio de encapsulación.
  • Permite especificar desde qué ámbito se tiene acceso a un determinado elemento.
  • Básicamente tenemos tres niveles:
  1. Desde la propia clase.
  2. Desde otras clases no relacionadas o desde el programa principal.
  3. Desde clases que extienden a otra (herencia).
  • Por tanto, existen tres tipos de visibilidad:
  1. public
  2. private
  3. protected
Icon present.gif
Tip:
  • public: tipo de visibilidad asignada por defecto a los métodos (si no se especifica).
  • En el caso de los atributos hay que declararla de forma explícita.
  • El uso de la palabra reservada var está depreciado; antes se usaba para declarar atributos públicos.


public
  • Los elementos públicos pueden ser accesibles desde cualquier ámbito en el que exista una referencia al objeto.
private
  • Los elementos con este modificador solo son accesibles desde el interior de la propia clase (ni siquiera desde clases heredadas).
  • En POO es habitual hacer todos los atributos privados y acceder a ellos mediante los métodos getter y setter.
Icon present.gif
Tip:

A un elemento private de una clase tampoco se puede acceder desde clases derivadas, pero en PHP sí se puede acceder a los atributos privados de otro objeto de la misma clase:

class A {
    private $foo;
 
    public function compara(A $b) {
        // Se puede acceder directamente al atributo privado $foo de otro objeto de la misma clase
        if ($this->foo == $b->foo) {
            return true;
        }
        return false;
    }
}


protected
  • Este tipo de visibilidad permite el acceso solo desde la propia clase y desde clases derivadas (herencia).
Siguiendo con nuestro ejemplo de Fecha, declaramos los atributos
class Fecha {
    // Declaración de atributos
    private int $dia;
    private int $mes;
    private int $year;
}

Los métodos

  • Es la forma de especificar el comportamiento de la clase: lo que el objeto sabe hacer dentro del programa.
  • Los métodos se definen usando la palabra reservada function.
  • En PHP orientado a objetos existen métodos especiales llamados #métodos mágicos, que se ejecutan automáticamente cuando ocurre un evento concreto (por ejemplo, al crear o destruir un objeto).
Métodos constructor y destructor
  • En PHP, a diferencia de Java, no podemos usar un método con el mismo nombre que la clase (desde PHP 7.4 genera error).
  • El constructor se define con el método mágico __construct() y se ejecuta automáticamente al instanciar un objeto.
  • De forma similar, el método __destruct() se ejecuta al destruir un objeto.
  • Ambos son opcionales y su invocación es transparente para el programador.
  • En __construct() podemos pasar parámetros para inicializar los atributos del objeto.
Ejemplo
construyendo nuestra clase
class Fecha {
    private int $dia;
    private int $mes;
    private int $year;
 
    public function __construct(int $d, int $m, int $y) {
        $this->dia = $d;
        $this->mes = $m;
        $this->year = $y;
    }
}
En este código aparecen dos conceptos importantes
  1. La seudovariable $this
  2. El operador de indirección ->

$this y el operador de indirección ->

  • Para acceder a los atributos o métodos de un objeto dentro de la clase usamos la seudovariable $this.
  • $this hace referencia al objeto actual (la instancia sobre la que se está ejecutando el método).
  • Si dentro de un método se omite $this->, PHP interpretará las variables como locales y no como atributos de la clase.



Icon activity.jpg
Observa el siguiente código
<?php
class Persona {  
    public $nombre;
    public $apellido;
 
    public function __construct(string $n, string $a) {
        // ERROR: asignación a variables locales, no a atributos
        $nombre = $n;
        $apellido = $a;
    }
}
 
$p = new Persona("María", "Ruiz");
echo "<h1>Nombre: $p->nombre</h1>";
echo "<h1>Apellido: $p->apellido</h1>";

  • Forma correcta:*
public function __construct(string $n, string $a) {
    $this->nombre = $n;
    $this->apellido = $a;
}





Icon key points.gif

Puntos clave

  • $this se lee como: “cuando exista una instancia de esta clase, accede al atributo o método de ese objeto”.



El operador de indirección ->
  • En PHP los objetos se manejan internamente como referencias en memoria.
  • Para acceder a sus elementos se usa el operador ->, que “indirecciona” hacia el atributo o método deseado.
  • Es la forma que tiene PHP de especificar a qué elemento concreto de un objeto se quiere acceder.

Declarando objetos: operador new

  • Permite crear instancias (objetos) en memoria.
  • Una clase describe la estructura común de un conjunto de objetos, su composición o plantilla.
  • En un programa, crearemos objetos (instancias) a partir de las clases mediante el operador new.
  • Una vez instanciado, tenemos una referencia al objeto y podemos usarlo.
  • Recordemos que cada objeto ocupa su propio espacio en memoria (con sus propios atributos y métodos).

Objetos4.png

Ejemplo en el programa principal:

require "Fecha.php";
 
$f1 = new Fecha(10, 2, 1998);

Acceso al contenido del objeto

  • Para acceder a un elemento de un objeto usamos los operadores -> o :: (este último para elementos estáticos).
Operador de indirección ->
  • Este operador permite acceder al contenido de un objeto a través de su referencia.
  • Cuando se usa dentro de la clase, suele acompañarse de $this;

cuando se usa fuera, de una variable objeto.

class Clase1 {
    public $propiedad1;
 
    public function __construct($valor) {
        // No se usa $ delante del nombre de la propiedad
        $this->propiedad1 = $valor; 
    }
}
 
$obj1 = new Clase1("verde");
$obj1->propiedad1 = "azul";

Sobrecarga

Es un concepto muy importante y básico en la programación orientada a objetos. La sobrecarga es una concreción del principio de polimorfismo.



Icon define.gif
Polimorfismo
  • Podemos tener varios métodos con el mismo nombre, pero con diferente número de parámetros o con parámetros de distinto tipo.
  • En tiempo de ejecución se ejecutará uno u otro en función de los parámetros reales que pasemos en la invocación del método.


  • Sin embargo, este aspecto en PHP no es del todo intuitivo: no existe la sobrecarga como la entendemos en otros lenguajes.
  • No obstante, disponemos de técnicas para poder simular la sobrecarga.
  • En muchos casos resulta fundamental, especialmente al sobrecargar el constructor de una clase.
  • Para simular la sobrecarga en PHP, aprovechamos que una variable que no tenga valor se considera del tipo null.
  • Lo veremos con una serie de ejemplos para dejar claro este concepto.
  • Tomamos como ejemplo una función:



Icon casestudy.gif
Ejemplo
function verTipoParametros($a = null, $b = null, $c = null){
    echo "Primer parámetro: ";
    var_dump($a);
    echo "Segundo parámetro: ";
    var_dump($b);
    echo "Tercer parámetro: ";
    var_dump($c);
}




  • Ahora la invocamos de diferentes maneras y observamos el resultado:



Icon casestudy.gif
Invocar sin parámetros reales
echo "Invocando a <strong>verTipoParametros()</strong><hr />";
verTipoParametros();
  • A pesar de que tiene tres parámetros, la invocamos sin argumentos.
  • El resultado será que cada parámetro, al ejecutar la función, será de tipo null con valor null (es un tipo válido en PHP).

FuncionSinParametrosReales.png




Icon casestudy.gif
Invocar con 1 parámetro real
echo "Invocando a <strong>verTipoParametros(5)</strong><hr />";
verTipoParametros(5);
  • En este caso invocamos con un solo parámetro de tipo entero.

Funcion1ParametrosReal.png




Icon casestudy.gif
Invocar con 2 parámetros reales
echo "Invocando a <strong>verTipoParametros(5,7)</strong><hr />";
verTipoParametros(5,7);
  • En este caso invocamos con dos parámetros de tipo entero.
  • Los parámetros dentro de la función serán tres: dos con valor entero y el tercero con valor y tipo null.

Funcion2ParametrosReal.png




Icon casestudy.gif
Invocar con 3 parámetros reales
echo "Invocando a <strong>verTipoParametros('pedro',5,9)</strong><hr />";
verTipoParametros('pedro',5,9);
  • En este caso pasamos tres parámetros: el primero de tipo string y los otros dos de tipo entero.

Funcion3ParametrosReal.png




Icon casestudy.gif
Invocar con 3 parámetros reales, uno de ellos un array
echo "Invocando a <strong>verTipoParametros([1,4,'maría'], true, 'sonia')</strong><hr />";
verTipoParametros([1,4,'maría'], true, 'sonia');
  • Ahora igualmente pasamos tres parámetros, pero uno de ellos es un array.

FuncionParametroRealArray.png



Sobrecargando el constructor

  • Usando esta forma de trabajar, vamos a sobrecargar el constructor de una clase.
  • Tomemos como ejemplo una clase Racional. Un número racional es un objeto que tiene numerador y denominador.

ClaseRacional.png

  • Queremos permitir crear el objeto de distintas formas:
$r1 = new Racional("8/5"); /* 8/5 */
$r2 = new Racional(5,4);   /* 5/4 */
$r3 = new Racional(5);     /* 5/1 */
$r4 = new Racional();      /* 1/1 */
  • Necesitamos que el constructor pueda responder a todas las situaciones.
  • Aplicando los conceptos vistos, solo tenemos que comprobar de qué tipo son los parámetros.
Icon present.gif
Tip: Recordar que null también es un tipo.


  • Vemos que podemos tener 0, 1 o 2 parámetros.

Por lo tanto, el constructor tendrá dos parámetros opcionales.

public function __construct($num = 1, $den = 1) {
    ...
}
  • Especificamos el código de cómo se podría implementar:
class Racional {
 
    private $num;
    private $den;
 
    public function __construct($num = 1, $den = 1) {
        // opciones:
        // new Racional()       => 1/1
        // new Racional(5)      => 5/1
        // new Racional("5/2")  => 5/2
        // new Racional(5,2)    => 5/2
        // Otra situación: no se instancia correctamente
 
        if (is_string($num)) {
            $numero = explode("/", $num);
            $num = $numero[0];
            $den = $numero[1];
        }
        $this->num = $num; 
        $this->den = $den;
    }
 
    /* Método para visualizar el objeto como cadena de caracteres */
    public function __toString() {
        return ($this->num . "/" . $this->den);
    }
 
    // Métodos privados para asignar valores según la forma de invocación
    private function racionalNum($num) {
        $this->num = $num;
        $this->den = 1;
    }
 
    /**
     * @param string $num número racional del tipo "a/b"
     * Hay muchas formas de poder descomponer esa cadena en dos números.
     */
    public function racionalCadena($num) {
        $partes = explode("/", $num);
        $this->num = (int) $partes[0];
        $this->den = (int) $partes[1];
    }
 
    public function racionalVacio() {
        $this->num = 1;
        $this->den = 1;
    }
 
    /* En este caso, si los valores son incorrectos, asigno el racional 1/1 */
    public function racionalNumDen($num, $den) {
        if (is_numeric($num) && is_numeric($den)) {
            $this->num = $num;
            $this->den = $den;
        } else {
            $this->num = 1;
            $this->den = 1;
        }
    }
}
Esta sería una posibilidad, pero podemos crear un código más compacto.

En la siguiente versión inicializamos los parámetros con un valor por defecto (1). Posteriormente, si el primer parámetro es una cadena, se divide en numerador y denominador. Hecho esto, solo queda asignar los valores a los atributos.

public function __construct($num = 1, $den = 1){
    if (is_string($num)){
        $numero = explode("/", $num);
        $num = $numero[0];
        $den = $numero[1];
    }
    $this->num = $num;
    $this->den = $den;
}
  • Probamos este constructor con el siguiente código:
$a = new Racional();
$b = new Racional(5);
$c = new Racional(5,6);
$d = new Racional("6/6");
 
echo "Valor del racional \$a = $a <br />";
echo "Valor del racional \$b = $b <br />";
echo "Valor del racional \$c = $c <br />";
echo "Valor del racional \$d = $d <br />";
  • Mostrando los siguientes resultados:
Valor del racional $a = 1/1  
Valor del racional $b = 5/1  
Valor del racional $c = 5/6  
Valor del racional $d = 6/6  

Sobrecarga con __call(...)

  • Otra forma de lograr un comportamiento similar es usando el método mágico __call($funcion, $parametros).
Icon present.gif
Tip: El método mágico __call(...) se ejecuta cuando invocamos un método que no existe en la clase.


  • Queremos usar un método llamado asigna() que nos permita cambiar el valor de un racional.
  • La forma de aportar el nuevo valor será la misma que la de construir el objeto.
$r1 = new Racional();      // construye el objeto 1/1
$r1->asigna("6/4");        // ahora el objeto vale 6/4
$r1->asigna();             // ahora el objeto vale 1/1
$r1->asigna(8);            // ahora el objeto vale 8/1
$r1->asigna(124, 6);       // ahora el objeto vale 124/6
  • La forma de proceder será usando los métodos privados creados anteriormente.
  • El siguiente código implementa la solución:
public function __call($metodo, $argumentos) {
    if ($metodo == "asigna") {
        switch (count($argumentos)) {
            case 0:
                $this->racionalVacio();
                break;
            case 2:
                $this->racionalNumDen($argumentos[0], $argumentos[1]);
                break;
            case 1:
                if (is_int($argumentos[0])) {
                    $this->racionalNum($argumentos[0]);
                } else {
                    $this->racionalCadena($argumentos[0]);
                }
                break;
        }
    }
}

Métodos static vs no static

  • En PHP, la idea de static es igual que en cualquier lenguaje de programación orientado a objetos.
  • Cuando un elemento (atributo o método) es estático, ese elemento es compartido por todos los objetos de la clase y persiste en memoria con su contenido mientras exista al menos un objeto de esa clase.
  • Como no pertenece a cada objeto individual, sino a la clase en general, también se les llama atributos o métodos de clase.
  • Para acceder a un elemento estático, necesitamos nombrar la clase (no el objeto). En PHP podemos hacerlo usando el operador self o el propio nombre de la clase junto con el operador de resolución de ámbito ::.



Icon activity.jpg
Usar constantes y elementos estáticos
Como ejemplo, vamos a implementar una clase Factura con los siguientes requisitos
  • La factura tendrá una constante llamada IVA.
  • Tendremos un atributo estático que especificará el número de facturas creadas.
  • Los atributos de cada factura serán importe_bruto y fecha.
  • Tendrá un método generarFactura() que mostrará:
  1. Factura de XXXX (el nombre se recibirá como argumento).
  2. Fecha (atributo).
  3. Importe base (atributo).
  4. IVA aplicado (constante de la clase).
  5. Total bruto (importe base más el IVA).
  • En el archivo index.php crearemos 5 facturas, visualizaremos el número de facturas, eliminaremos dos de ellas y volveremos a visualizar el número de facturas. Finalmente imprimiremos las dos facturas restantes.




  • Es muy común tener un atributo static que cuente cuántos objetos existen de una clase.
  • En la siguiente imagen se ilustra cómo al crear varios objetos, cada uno se instancia por separado en memoria:
Estatico1.png
  • Cuando añadimos un elemento estático, solo habrá una copia en memoria, compartida por todos los objetos de la clase:
Estatico2.png
  • Vemos el código y cómo se accede al elemento estático:
<?php
class Racional {
    static public $cuenta_racionales = 0;
 
    private $num; // Numerador
    private $den; // Denominador
 
    public function __construct($num, $den) {
        self::$cuenta_racionales++;
        $this->num = $num;
        $this->den = $den;
    }
}
?>
  • El uso:
<?php
require_once "Racional.php";
 
$r1 = new Racional(5,4);
$r2 = new Racional(5,4);
$r3 = new Racional(5,4);
 
echo "<h1>Ahora tenemos " . Racional::$cuenta_racionales . " objetos Racional</h1>";
 
$r4 = new Racional(5,4);
$r5 = new Racional(5,4);
 
echo "<h1>Ahora tenemos " . Racional::$cuenta_racionales . " objetos Racional</h1>";
 
$r6 = new Racional(5,4);
$r7 = new Racional(5,4);
 
// Observa (y esto es propio de PHP) que puedo acceder a un elemento estático
// tanto a través del nombre de la clase como desde un objeto
echo "<h2>Podemos acceder con los objetos:</h2>";
echo "<h3>Según r1: " . $r1::$cuenta_racionales . "</h3>";
echo "<h3>Según r2: " . $r2::$cuenta_racionales . "</h3>";
echo "<h3>Según r3: " . $r3::$cuenta_racionales . "</h3>";
echo "<h3>Según la clase: " . Racional::$cuenta_racionales . "</h3>";
?>
  • La salida:

AppEstatica1.png

---

  • Vamos a implementar las operaciones con números racionales.

Antes, recordemos las operaciones básicas:

Sumar

Suma racionales.png

Restar

Resta racionales.png

Multiplicar

Mult racionales.png

Dividir

Division racional.png

  • Si la operación la implementamos como un método no estático, lo que estaremos haciendo es sumar al objeto actual otro objeto Racional que pasamos como argumento.

Podemos modificar el objeto actual o devolver un nuevo objeto (lo más correcto).

/**
 * Suma al racional actual el racional recibido como parámetro.
 * @param Racional $n1
 * @return Racional
 */
public function sumar(Racional $n1) {
    $den = $this->den * $n1->getDen();
    $num = $this->num * $n1->getDen() + $this->den * $n1->getNum();
    return new Racional($num, $den);
}
  • Para usarlo:
$r1 = new Racional(7,6);
$r2 = new Racional(9,4);
 
$r3 = $r1->sumar($r2);
echo "$r1 + $r2 = $r3";
  • La salida:

SumarNoEstatico.png

---

  • Si la operación la realizamos como un método estático, estaremos sumando dos objetos Racional y devolviendo un nuevo objeto como resultado:
static public function sum_static(Racional $r1, Racional $r2){
    $n = $r1->getNum() * $r2->getDen() + $r1->getDen() * $r2->getNum();
    $d = $r1->getDen() * $r2->getDen();
    return new Racional($n, $d);
}
  • Para usarlo:
$r1 = new Racional(7,6);
$r2 = new Racional(9,4);
 
$r3 = Racional::sum_static($r1, $r2);
echo "$r1 + $r2 = $r3";
  • La salida:

SumarEstatico.png

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}}}