Sobrescritura de métodos
Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy — lección 23 de 91.
A veces, el método heredado de una clase padre no se ajusta del todo a lo que la clase hija necesita. La sobrescritura de métodos (method overriding) permite que una clase hija proporcione su propia implementación de un método que ya existe en la clase padre.
Para sobrescribir un método, simplemente define un método en la clase hija con el mismo nombre que el método del padre:
<?php
class Animal {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function speak() {
return "$this->name makes a sound";
}
}
class Cat extends Animal {
public function speak() {
return "$this->name says meow";
}
}
$cat = new Cat("Whiskers");
echo $cat->speak();
Resultado:
Whiskers says meowLa clase Cat reemplaza completamente el método speak() del padre con su propia versión. Cuando llamas a speak() en un objeto de tipo gato, PHP utiliza la implementación del hijo.
También puedes extender el comportamiento del padre combinando parent:: con tu propia lógica:
<?php
class Dog extends Animal {
public function speak() {
return parent::speak() . " - woof woof!";
}
}
$dog = new Dog("Rex");
echo $dog->speak();
Salida:
Rex makes a sound - woof woof!Punto clave: La sobrescritura de métodos permite que las clases hijas personalicen el comportamiento heredado. Puedes reemplazar completamente un método o usar parent:: para ampliar la implementación original.
Desafío
FácilConstruyamos un sistema de notificaciones que demuestre cómo las clases hijas pueden reemplazar completamente o extender los métodos de los padres a través de la sobrescritura de métodos (method overriding).
Crearás tres archivos que trabajan juntos para enviar diferentes tipos de notificaciones, cada uno con su propio comportamiento único:
Notification.php— Define una claseNotificationque sirva como base para todos los tipos de notificación. Debe tener una propiedad pública$recipienty un constructor que acepte y establezca el destinatario. Incluye un métodosend($message)que devuelva"Sending to $this->recipient: $message".UrgentNotification.php— Define una claseUrgentNotificationque extienda deNotification. Incluye el archivo Notification al principio. Esta clase debe sobrescribir completamente el métodosend($message)para devolver"URGENT to $this->recipient: $message!!!"— nota el prefijo "URGENT" y los signos de exclamación al final. Esto demuestra el reemplazo total del comportamiento del padre.LoggedNotification.php— Define una claseLoggedNotificationque extienda deNotification. Incluye el archivo Notification al principio. Esta clase debe sobrescribirsend($message)pero basándose en la implementación del padre: llama aparent::send($message)y añade" [logged]"al resultado. Esto demuestra la extensión en lugar del reemplazo del comportamiento.
En main.php, incluye los tres archivos de clases de notificación. Recibirás dos entradas: el nombre del destinatario y el mensaje a enviar. Crea una instancia de cada tipo de notificación (todas usando el mismo destinatario), luego llama a send() con el mensaje en cada una. Imprime cada resultado en su propia línea en este orden: notificación regular, notificación urgente y luego notificación registrada.
Este desafío muestra ambos enfoques de la sobrescritura de métodos: UrgentNotification reemplaza completamente la lógica del padre con su propio formato, mientras que LoggedNotification utiliza parent:: para mantener el comportamiento original y añadirle algo más.
Hoja de referencia
La anulación de métodos (method overriding) permite que una clase hija proporcione su propia implementación de un método heredado de una clase padre.
Para anular un método, defina un método en la clase hija con el mismo nombre que el método del padre:
<?php
class Animal {
public function speak() {
return "makes a sound";
}
}
class Cat extends Animal {
public function speak() {
return "says meow";
}
}
La clase hija reemplaza completamente la implementación del método del padre. Cuando se llama en un objeto hijo, PHP utiliza la versión del hijo.
Para extender el comportamiento del padre en lugar de reemplazarlo, use parent:: para llamar al método del padre y añadir su propia lógica:
<?php
class Dog extends Animal {
public function speak() {
return parent::speak() . " - woof woof!";
}
}
Esto combina el comportamiento original del padre con funcionalidad adicional de la clase hija.
Pruébalo tú mismo
<?php
require_once 'Notification.php';
require_once 'UrgentNotification.php';
require_once 'LoggedNotification.php';
// Leer la entrada
$recipient = trim(fgets(STDIN));
$message = trim(fgets(STDIN));
// TODO: Crear una instancia de cada tipo de notificación (todas usando el mismo destinatario)
// TODO: Llamar a send() con el mensaje en cada notificación
// Imprimir cada resultado en su propia línea en este orden:
// 1. Notificación regular
// 2. Notificación urgente
// 3. Notificación registrada
?>Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a OOPClases vs ObjetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Resumen - Calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasResumen - Jerarquía de empleados7Encapsulamiento
Público, Protegido, PrivadoModificadores de acceso a fondoGetters y SettersOcultamiento de informaciónPromoción de constructor (8.0)Resumen - Sistema de registros de estudiantes10Conceptos avanzados de POO
Composición vs. HerenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibers (PHP 8.1)Clonación de objetos a fondoGeneradores e Iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Espacios de nombres y Autoloading
Introducción a los espacios de nombresLa palabra clave useEstándar de Autoloading PSR-4Autoloader de ComposerResumen - Proyecto organizado5Interfaces y Contratos
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesInterfaz vs Clase AbstractaType Hinting con InterfacesResumen - Calculadora de Formas8Métodos mágicos
Introducción a los métodos mágicos__toString y __debugInfo__get, __set, __isset, __unset__call y __callStatic__clone y clonación de objetos__serialize y __unserializeResumen - Colección personalizada3Propiedades de clase
Propiedades de instancia vs. estáticasConstantes en clasesMétodos y propiedades estáticosPropiedades privadas y protegidasPropiedades de solo lectura (PHP 8.1)Resumen - Gestor de cuenta bancaria6Polimorfismo
Sobrescritura de métodos revisadaPolimorfismo mediante interfacesType Hinting y tipos de uniónEnlace estático tardíoResumen - Procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos de TraitsMétodos abstractos en TraitsTraits frente a herencia12Patrones de diseño Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy