PHP

PHP

Tutorial PHP: Herencia

PHP: Aprende sobre clases padre e hijo, herencia, y sobrescritura de métodos para mejorar la reutilización de código.

Aprende PHP GRATIS y certifícate

Clases padre e hijo

En la programación orientada a objetos, las clases padre e hijo son fundamentales para establecer relaciones de herencia entre clases. Una clase padre (o superclase) define propiedades y métodos que pueden ser heredados por una o varias clases hijo (o subclases), permitiendo así la reutilización y organización eficiente del código.

Por ejemplo, considera una clase Vehiculo que encapsula atributos y comportamientos comunes a todos los vehículos, como mover() o detener(). Las clases hijo como Coche y Moto pueden derivar de Vehiculo, heredando estas propiedades y métodos, y agregando características específicas.

La herencia facilita la extensibilidad del código al permitir que las clases hijo amplíen o modifiquen el comportamiento de la clase padre. Esto es útil para crear estructuras jerárquicas claras y para implementar funcionalidades especializadas sin duplicar código.

Es importante destacar que en PHP una clase hijo solo puede heredar de una única clase padre, ya que no se admite la herencia múltiple directa. Sin embargo, se pueden utilizar traits para incorporar funcionalidades adicionales y simular cierto comportamiento de herencia múltiple.

La relación entre clases padre e hijo es esencial para aplicar principios como el principio de sustitución de Liskov, que permite utilizar objetos de la clase hijo donde se espera un objeto de la clase padre, manteniendo la cohesión y flexibilidad del código.

Uso de la palabra clave extends

En PHP, la palabra clave extends se emplea para indicar que una clase hereda de otra existente. Esto permite que la nueva clase (clase hijo) adquiera las propiedades y métodos de la clase padre, facilitando la reutilización y organización del código.

Por ejemplo, supongamos una clase Animal que define comportamientos generales:

<?php
class Animal
{
    protected $nombre;

    public function __construct($nombre)
    {
        $this->nombre = $nombre;
    }

    public function comer()
    {
        echo "$this->nombre está comiendo.\n";
    }
}

Si queremos crear una clase Perro que herede de Animal, utilizamos extends:

class Perro extends Animal
{
    public function ladrar()
    {
        echo "$this->nombre está ladrando.\n";
    }
}

Al hacerlo, Perro hereda el constructor y el método comer() de Animal. Podemos crear una instancia de Perro y utilizar ambos métodos:

$miPerro = new Perro("Firulais");
$miPerro->comer();
$miPerro->ladrar();

La salida será:

Firulais está comiendo.
Firulais está ladrando.

La herencia con extends permite que la clase hijo amplíe o especialice el comportamiento de la clase padre. Además, es posible acceder a los métodos y propiedades protegidas de la clase padre desde la clase hijo, manteniendo el encapsulamiento.

Es importante recordar que en PHP una clase solo puede extender de una única clase (herencia simple). Sin embargo, se pueden combinar varias funcionalidades utilizando traits, que se verán en secciones posteriores.

Al utilizar extends, asegúrate de que la clase padre esté definida antes de la clase hijo. La correcta aplicación de extends es esencial para construir jerarquías de clases y aprovechar al máximo la programación orientada a objetos en PHP.

Sobrescritura de métodos

La sobrescritura de métodos es un mecanismo en programación orientada a objetos que permite a una clase hijo redefinir un método heredado de su clase padre. Esto es útil cuando el comportamiento definido en la clase padre no encaja completamente con las necesidades de la clase hijo, y se requiere una implementación específica.

Al sobrescribir un método, el nombre y la firma deben coincidir exactamente con los del método en la clase padre. La clase hijo puede alterar el comportamiento, extendiendo o reemplazando la funcionalidad original.

Por ejemplo, considera una clase padre Empleado:

<?php
class Empleado
{
    protected $nombre;

    public function __construct($nombre)
    {
        $this->nombre = $nombre;
    }

    public function calcularSalario()
    {
        echo "El salario de $this->nombre es base.\n";
    }
}

Ahora, una clase hijo Gerente puede sobrescribir el método calcularSalario() para reflejar una estructura salarial diferente:

class Gerente extends Empleado
{
    public function calcularSalario()
    {
        echo "El salario de $this->nombre incluye bonificaciones.\n";
    }
}

Al crear instancias de ambas clases, observarás diferentes comportamientos:

$empleado = new Empleado("Ana");
$empleado->calcularSalario(); // Salida: El salario de Ana es base.

$gerente = new Gerente("Luis");
$gerente->calcularSalario(); // Salida: El salario de Luis incluye bonificaciones.

En este caso, la clase Gerente ha sobrescrito el método calcularSalario() para proporcionar una implementación específica.

Es posible también llamar al método original de la clase padre utilizando parent::. Esto permite conservar el comportamiento original y añadir funcionalidades adicionales:

class Gerente extends Empleado
{
    public function calcularSalario()
    {
        parent::calcularSalario();
        echo "$this->nombre recibe beneficios extra.\n";
    }
}

La salida ahora será:

El salario de Luis es base.
Luis recibe beneficios extra.

La sobrescritura de métodos es esencial para aplicar el polimorfismo, permitiendo que objetos de distintas clases respondan de manera diferente al mismo método. Además, mejora la flexibilidad y extensibilidad del código al adaptar comportamientos heredados a necesidades específicas.

Al sobrescribir métodos, es importante respetar la visibilidad del método original. Si el método en la clase padre es public, el método sobrescrito debe ser public también. Reducir la visibilidad puede generar errores y violar los principios de la herencia.

Además, a partir de PHP 7.4, es posible especificar tipos de retorno y parámetros en los métodos. Al sobrescribir un método, los tipos declarados deben ser compatibles con los del método original:

class Empleado
{
    public function obtenerID(): int
    {
        return 123;
    }
}

class Gerente extends Empleado
{
    public function obtenerID(): int
    {
        return 456;
    }
}

Mantener la coherencia en los tipos garantiza que la sobrescritura se realice correctamente y que el código sea robusto y fácil de mantener.

Uso de parent::

En PHP, parent:: es una sintaxis que permite a una clase hijo acceder a métodos y propiedades de su clase padre. Esto es especialmente útil cuando la clase hijo ha sobrescrito un método y necesita invocar la implementación original de la clase padre.

Por ejemplo, al sobrescribir el constructor en una clase hijo, es común llamar al constructor de la clase padre para asegurarse de que todas las propiedades heredadas se inicializan correctamente:

<?php
class Vehiculo
{
    protected $marca;

    public function __construct($marca)
    {
        $this->marca = $marca;
    }
}

class Coche extends Vehiculo
{
    private $modelo;

    public function __construct($marca, $modelo)
    {
        parent::__construct($marca);
        $this->modelo = $modelo;
    }
}

En este ejemplo, la clase Coche extiende de Vehiculo y sobrescribe el método __construct(). Mediante parent::__construct($marca);, se invoca el constructor de la clase padre, inicializando la propiedad $marca.

Además de constructores, parent:: se utiliza para acceder a métodos sobrescritos en la clase hijo:

class Empleado
{
    protected $nombre;

    public function __construct($nombre)
    {
        $this->nombre = $nombre;
    }

    public function presentar()
    {
        echo "Hola, soy $this->nombre.\n";
    }
}

class Gerente extends Empleado
{
    public function presentar()
    {
        parent::presentar();
        echo "Soy el gerente de la empresa.\n";
    }
}

$gerente = new Gerente("Laura");
$gerente->presentar();

La salida será:

Hola, soy Laura.
Soy el gerente de la empresa.

Aquí, parent::presentar(); permite que el método presentar() del Gerente mantenga la presentación básica definida en la clase Empleado, y añada información específica.

También es posible utilizar parent:: para acceder a propiedades protegidas o públicas de la clase padre:

class Animal
{
    protected $especie = "Animal genérico";

    public function obtenerEspecie()
    {
        return $this->especie;
    }
}

class Perro extends Animal
{
    protected $especie = "Perro";

    public function describir()
    {
        echo "Este es un " . parent::obtenerEspecie() . ".\n";
        echo "Más específicamente, es un $this->especie.\n";
    }
}

$perro = new Perro();
$perro->describir();

La salida será:

Este es un Animal genérico.
Más específicamente, es un Perro.

En este caso, parent::obtenerEspecie(); invoca el método de la clase padre para obtener la especie general, mientras que $this->especie obtiene la propiedad sobrescrita en la clase hijo.

Es importante notar que parent:: solo puede acceder a miembros que sean públicos o protegidos en la clase padre. No es posible acceder a propiedades o métodos privados, ya que estos no se heredan.

Cuando se trabajan con métodos estáticos, parent:: también es aplicable:

class Logger
{
    public static function log($mensaje)
    {
        echo "Log: $mensaje\n";
    }
}

class FileLogger extends Logger
{
    public static function log($mensaje)
    {
        parent::log($mensaje);
        // Código adicional para escribir en un archivo
        echo "El mensaje ha sido guardado en el archivo.\n";
    }
}

FileLogger::log("Mensaje de prueba");

La salida será:

Log: Mensaje de prueba
El mensaje ha sido guardado en el archivo.

Aquí, parent::log($mensaje); llama al método estático de la clase Logger, aprovechando su funcionalidad antes de añadir operaciones específicas de FileLogger.

Además, en contextos donde varias clases comparten una jerarquía de herencia, parent:: siempre se refiere a la clase inmediatamente superior. Si existe una cadena de herencia más extensa, parent:: no accederá a métodos o propiedades más allá de la clase padre directa.

Otra aplicación de parent:: es en combinación con los métodos mágicos como __call() o __toString(). Si se sobrescriben en la clase hijo, se puede utilizar parent::__call() para mantener parte del comportamiento original:

class Base
{
    public function __call($nombre, $argumentos)
    {
        echo "Llamando al método $nombre en la clase Base.\n";
    }
}

class Derivada extends Base
{
    public function __call($nombre, $argumentos)
    {
        echo "Llamando al método $nombre en la clase Derivada.\n";
        parent::__call($nombre, $argumentos);
    }
}

$obj = new Derivada();
$obj->metodoInexistente();

La salida será:

Llamando al método metodoInexistente en la clase Derivada.
Llamando al método metodoInexistente en la clase Base.

De esta forma, se puede extender la funcionalidad de los métodos mágicos sin perder la lógica implementada en la clase padre.

Finalmente, es esencial comprender que el uso adecuado de parent:: promueve la reutilización de código y el cumplimiento de principios de buen diseño orientado a objetos. Al aprovechar las implementaciones existentes en la clase padre, se evita la duplicación y se facilita el mantenimiento y evolución del código.

Para seguir leyendo hazte Plus

¿Ya eres Plus? Accede a la app

20 % DE DESCUENTO

Plan mensual

19.00 /mes

15.20 € /mes

Precio normal mensual: 19 €
58 % DE DESCUENTO

Plan anual

10.00 /mes

8.00 € /mes

Ahorras 132 € al año
Precio normal anual: 120 €
Aprende PHP GRATIS online

Todas las lecciones de PHP

Accede a todas las lecciones de PHP y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Php

PHP

Introducción Y Entorno

Instalación Y Primer Programa De Php

PHP

Introducción Y Entorno

Tipos De Datos, Variables Y Constantes

PHP

Sintaxis

Operadores Y Expresiones

PHP

Sintaxis

Estructuras De Control

PHP

Sintaxis

Funciones Y Llamada De Funciones

PHP

Sintaxis

Cadenas De Texto Y Manipulación

PHP

Sintaxis

Manejo De Números

PHP

Sintaxis

Manejo De Fechas Y Tiempo

PHP

Sintaxis

Manejo De Arrays

PHP

Sintaxis

Introducción A La Poo En Php

PHP

Programación Orientada A Objetos

Clases Y Objetos

PHP

Programación Orientada A Objetos

Constructores Y Destructores

PHP

Programación Orientada A Objetos

Herencia

PHP

Programación Orientada A Objetos

Encapsulación

PHP

Programación Orientada A Objetos

Polimorfismo

PHP

Programación Orientada A Objetos

Interfaces

PHP

Programación Orientada A Objetos

Traits

PHP

Programación Orientada A Objetos

Namespaces

PHP

Programación Orientada A Objetos

Autoloading De Clases

PHP

Programación Orientada A Objetos

Manejo De Errores Y Excepciones

PHP

Programación Orientada A Objetos

Manejo De Archivos

PHP

Programación Orientada A Objetos

Patrones De Diseño

PHP

Programación Orientada A Objetos

Introducción A Los Formularios En Php

PHP

Formularios

Procesamiento De Datos De Formularios

PHP

Formularios

Manejo De Archivos En Formularios

PHP

Formularios

Redirecciones Y Retroalimentación Al Usuario

PHP

Formularios

Formularios Dinámicos Y Separación De Lógica

PHP

Formularios

Introducción A La Persistencia En Php

PHP

Persistencia

Conexión A Bases De Datos

PHP

Persistencia

Consultas Y Operaciones Crud

PHP

Persistencia

Gestión De Transacciones

PHP

Persistencia

Manejo De Errores Y Excepciones En Base De Datos

PHP

Persistencia

Patrones De Acceso A Datos

PHP

Persistencia

Concepto De Sesiones En Php

PHP

Sesiones Y Cookies

Configuración De Sesiones

PHP

Sesiones Y Cookies

Cookies

PHP

Sesiones Y Cookies

Manejo Avanzado De Sesiones Y Cookies

PHP

Sesiones Y Cookies

Principales Vulnerabilidades En Php

PHP

Seguridad

Seguridad En Formularios Y Entrada De Datos

PHP

Seguridad

Protección Frente A Inyección Sql

PHP

Seguridad

Gestión De Contraseñas Y Cifrado

PHP

Seguridad

Seguridad En Sesiones Y Cookies

PHP

Seguridad

Configuraciones De Php Para Seguridad

PHP

Seguridad

Introducción Al Testing En Php

PHP

Testing

Phpunit

PHP

Testing

Cobertura De Código En Testing

PHP

Testing

Test Doubles (Mocks, Stubs, Fakes, Spies)

PHP

Testing

Pruebas De Integración Y Funcionales

PHP

Testing

Accede GRATIS a PHP y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  1. Comprender el concepto de herencia en programación orientada a objetos.
  2. Aprender a utilizar la palabra clave extends en PHP.
  3. Conocer la sobrescritura de métodos y su aplicación práctica.
  4. Identificar cómo parent:: facilita la accesibilidad a métodos heredados.
  5. Explorar ejemplos claros de aplicación de herencia en PHP.