La herencia en PHP permite que una clase hija reutilice el código de su clase padre y añada o cambie comportamiento sin repetir código. Con extends una clase hereda todas las propiedades y métodos públicos y protegidos de su padre, y con parent:: puedes invocar la implementación original del método sobreescrito.
Herencia básica con extends
<?php
class Animal
{
public function __construct(
protected string $nombre,
protected int $edad,
) {}
public function describir(): string
{
return "{$this->nombre}, {$this->edad} años";
}
public function sonido(): string
{
return '...';
}
}
class Perro extends Animal
{
public function __construct(
string $nombre,
int $edad,
private string $raza,
) {
parent::__construct($nombre, $edad);
}
public function sonido(): string
{
return 'Guau';
}
public function describir(): string
{
return parent::describir() . ", raza: {$this->raza}";
}
}
$perro = new Perro('Rex', 3, 'Labrador');
echo $perro->describir(); // Rex, 3 años, raza: Labrador
echo $perro->sonido(); // Guau
?>
Llamar al constructor del padre con parent::__construct()
Cuando la clase hija define su propio __construct(), el del padre no se llama automáticamente. Es tu responsabilidad invocarlo con parent::__construct() si es necesario:
<?php
class Vehiculo
{
public function __construct(
protected string $marca,
protected int $anio,
) {
echo "Vehículo creado: {$this->marca}n";
}
}
class Coche extends Vehiculo
{
public function __construct(
string $marca,
int $anio,
private int $puertas,
) {
parent::__construct($marca, $anio); // imprime el mensaje del padre
echo "Coche con {$this->puertas} puertasn";
}
public function info(): string
{
return "{$this->marca} ({$this->anio}), {$this->puertas} puertas";
}
}
$c = new Coche('Toyota', 2023, 4);
// Vehículo creado: Toyota
// Coche con 4 puertas
echo $c->info(); // Toyota (2023), 4 puertas
?>
Sobreescribir métodos y mantener la firma
Al sobreescribir un método, la firma de la clase hija debe ser compatible con la del padre. El tipo de retorno puede ser más específico (covariante) pero no más amplio:
<?php
class Forma
{
public function area(): float
{
return 0.0;
}
public function descripcion(): string
{
return 'Forma con área ' . $this->area();
}
}
class Circulo extends Forma
{
public function __construct(private float $radio) {}
public function area(): float
{
return M_PI * $this->radio ** 2;
}
}
class Rectangulo extends Forma
{
public function __construct(
private float $ancho,
private float $alto,
) {}
public function area(): float
{
return $this->ancho * $this->alto;
}
}
$formas = [new Circulo(5), new Rectangulo(4, 6)];
foreach ($formas as $f) {
echo $f->descripcion() . "n";
}
// Forma con área 78.539816339745
// Forma con área 24
?>
Evitar subclases con final
La palabra clave final se puede aplicar a clases enteras o a métodos individuales para impedir que se extiendan o sobreescriban:
<?php
class Pago
{
final public function registrarAuditoria(string $accion): void
{
// Este método nunca puede ser sobreescrito
$fecha = date('Y-m-d H:i:s');
file_put_contents('/tmp/audit.log', "$fecha: $accionn", FILE_APPEND);
}
public function procesar(): void
{
$this->registrarAuditoria('pago iniciado');
// lógica de pago...
}
}
final class PagoSeguro extends Pago
{
public function procesar(): void
{
// puede extender Pago, pero nadie puede extender PagoSeguro
parent::procesar();
}
}
// class PagoMuySeguro extends PagoSeguro {} // Fatal error
?>
instanceof y comprobación de tipo en herencia
<?php
class Animal {}
class Mamifero extends Animal {}
class Perro extends Mamifero {}
$perro = new Perro();
var_dump($perro instanceof Perro); // true
var_dump($perro instanceof Mamifero); // true
var_dump($perro instanceof Animal); // true
// Constantes heredadas
class Base
{
const VERSION = '1.0';
}
class Hija extends Base {}
echo Hija::VERSION; // 1.0 la constante se hereda
?>
La documentación oficial sobre herencia en PHP cubre todos los detalles de compatibilidad de firmas, herencia de constantes y el comportamiento de parent:: en distintos contextos.
