Menu
Coddy logo textTech

Resolución de conflictos de 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 lanza un error fatal. Debes indicarle explícitamente a PHP cómo manejar este conflicto utilizando 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 occurred

El 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() por defecto. El operador as crea un alias, permitiéndote acceder al método del otro trait bajo 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 privado dentro de la clase Person, aunque sea público en el trait. La resolución de conflictos te brinda un control detallado sobre cómo los métodos del trait se integran en tus clases.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de notificación donde diferentes canales pueden enviar mensajes, pero necesitamos resolver conflictos cuando múltiples traits proporcionan el mismo nombre de método.

Organizarás tu código en cuatro archivos:

  • EmailNotifier.php — Crea un trait llamado EmailNotifier con un método notify(string $message) que devuelva "Email: $message".
  • SmsNotifier.php — Crea un trait llamado SmsNotifier con un método notify(string $message) que devuelva "SMS: $message".
  • AlertService.php — Crea una clase AlertService que use ambos traits. Dado que ambos traits tienen un método notify(), deberás resolver este conflicto:
    • Usa EmailNotifier::notify como el método notify() por defecto
    • Crea un alias notifyBySms para el método SmsNotifier::notify
    También añade un método notifyAll(string $message) que llame a ambos métodos de notificación y los devuelva combinados en líneas separadas.
  • main.php — Incluye todos los archivos necesarios y crea una instancia de AlertService. 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

Esto demuestra cómo insteadof resuelve qué método del trait prevalece cuando hay un conflicto de nombres, mientras que as te permite mantener el acceso al método del otro trait bajo un nombre diferente.

Hoja de referencia

Cuando múltiples traits definen métodos con el mismo nombre, PHP requiere una resolución de conflictos explícita utilizando los operadores insteadof y as.

El operador insteadof selecciona qué método del trait se utilizará por defecto:

<?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"); // File: Error occurred
$app->logToDatabase("Error occurred"); // DB: Error occurred

El operador as crea un alias para un método de un trait, permitiendo el acceso bajo un nombre diferente.

También puedes usar as para cambiar la visibilidad del método:

<?php
trait Greeting {
    public function sayHello(): void {
        echo "Hello!";
    }
}

class Person {
    use Greeting {
        sayHello as private;
    }
}

Pruébalo tú mismo

<?php
require_once 'AlertService.php';

// Leer entrada
$message = trim(fgets(STDIN));

// TODO: Crear una instancia de AlertService

// TODO: Imprimir el resultado de llamar a notify() con el mensaje

// TODO: Imprimir el resultado de llamar a notifyBySms() con el mensaje

// TODO: Imprimir el resultado de llamar a notifyAll() con el mensaje
?>
quiz iconPonte a prueba

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