Resolución de conflictos entre Traits
Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy. Lección 53 de 91.
Cuando dos traits definen métodos con el mismo nombre, PHP produce un error fatal. Debes indicar explícitamente a PHP cómo gestionar este conflicto mediante los operadores insteadof y as.
<?php
trait FileLogger {
public function log(string $message): void {
echo "File: $message";
}
}
trait DatabaseLogger {
public function log(string $message): void {
echo "DB: $message";
}
}
class Application {
use FileLogger, DatabaseLogger {
FileLogger::log insteadof DatabaseLogger;
DatabaseLogger::log as logToDatabase;
}
}
$app = new Application();
$app->log("Error occurred");
$app->logToDatabase("Error occurred");
Salida:
File: Error occurred
DB: Error occurredEl operador insteadof elige qué método del trait usar cuando hay un conflicto. En este ejemplo, FileLogger::log gana y se convierte en el método log() predeterminado. El operador as crea un alias, lo que te permite acceder al método del otro trait con un nombre diferente.
También puedes usar as para cambiar la visibilidad de un método:
<?php
trait Greeting {
public function sayHello(): void {
echo "Hello!";
}
}
class Person {
use Greeting {
sayHello as private;
}
}
Esto hace que sayHello() sea privada dentro de la clase Person, aunque sea pública en el trait. La resolución de conflictos te proporciona un control detallado sobre cómo se integran los métodos del trait en tus clases.
Desafío
FácilConstruyamos un sistema de notificaciones en el que distintos canales puedan enviar mensajes, pero necesitamos resolver los conflictos cuando varios traits proporcionan el mismo nombre de método.
Organizarás tu código en cuatro archivos:
EmailNotifier.php: Crea un trait llamadoEmailNotifiercon un métodonotify(string $message)que devuelve"Email: [message]".SmsNotifier.php: Crea un trait llamadoSmsNotifiercon un métodonotify(string $message)que devuelve"SMS: [message]".AlertService.php: Crea una claseAlertServiceque use ambos traits. Como ambos traits tienen un métodonotify(), tendrás que resolver este conflicto:- Usa
EmailNotifier::notifycomo métodonotify()predeterminado - Crea un alias
notifyBySmspara el métodoSmsNotifier::notify
notifyAll(string $message)que llame a ambos métodos de notificación y los devuelva combinados en líneas separadas.- Usa
main.php: Incluye todos los archivos necesarios y crea una instancia deAlertService. Recibirás una entrada: una cadena de mensaje. Imprime tres líneas:- El resultado de llamar a
notify()con el mensaje - El resultado de llamar a
notifyBySms()con el mensaje - El resultado de llamar a
notifyAll()con el mensaje
- El resultado de llamar a
Esto demuestra cómo insteadof resuelve qué método de trait prevalece cuando existe un conflicto de nombres, mientras que as te permite conservar el acceso al método del otro trait con un nombre diferente.
Pruébalo tú mismo
<?php
require_once 'AlertService.php';
// Leer entrada
$message = trim(fgets(STDIN));
// TODO: Crea una instancia de AlertService
// TODO: Imprime el resultado de llamar a notify() con el mensaje
// TODO: Imprime el resultado de llamar a notifyBySms() con el mensaje
// TODO: Imprime el resultado de llamar a notifyAll() con el mensaje
?>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 la POO
Archivos externosIntroducción a la POOClases frente a objetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Repaso: calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasRepaso - Jerarquía de empleados7Encapsulación
Público, protegido, privadoModificadores de acceso en profundidadGetters y settersOcultación de la informaciónPromoción del constructor (8.0)Repaso: sistema de registros de estudiantes10Conceptos avanzados de OOP
Composición vs. herenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibras (PHP 8.1)Análisis profundo de la clonación de objetosGeneradores e iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Namespaces y carga automática
Introducción a los NamespacesLa palabra clave useEstándar de carga automática PSR-4Autoloader de ComposerRepaso: proyecto organizado5Interfaces y contratos
Introducción a las interfacesImplementación de interfacesImplementación de múltiples interfacesInterfaces vs. clase abstractaTipado con interfacesRepaso - 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 __unserializeRepaso: 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)Repaso: gestor de cuentas bancarias6Polimorfismo
Repaso de la sobrescritura de métodosPolimorfismo mediante interfacesAnotaciones de tipo y tipos uniónEnlace estático tardíoRepaso: procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos entre TraitsMétodos abstractos en TraitsTraits frente a la herencia12Patrones de diseño, parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón StrategyPractica por tu cuenta: Compilador de PHP online