Menu
Coddy logo textTech

Résolution des conflits de Traits

Fait partie de la section Programmation Orientée Objet du Journey PHP de Coddy — leçon 53 sur 91.

Lorsque deux traits définissent des méthodes portant le même nom, PHP génère une erreur fatale. Vous devez explicitement indiquer à PHP comment gérer ce conflit en utilisant les opérateurs insteadof et 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");

Sortie :

File: Error occurred
DB: Error occurred

L'opérateur insteadof choisit la méthode de quel trait utiliser lorsqu'il y a un conflit. Dans cet exemple, FileLogger::log l'emporte et devient la méthode log() par défaut. L'opérateur as crée un alias, vous permettant d'accéder à la méthode de l'autre trait sous un nom différent.

Vous pouvez également utiliser as pour modifier la visibilité d'une méthode :

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

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

Cela rend sayHello() privée au sein de la classe Person, même si elle est publique dans le trait. La résolution de conflits vous donne un contrôle précis sur la manière dont les méthodes de trait s'intègrent dans vos classes.

challenge icon

Défi

Facile

Construisons un système de notification où différents canaux peuvent envoyer des messages, mais nous devons résoudre les conflits lorsque plusieurs traits fournissent le même nom de méthode.

Vous organiserez votre code sur quatre fichiers :

  • EmailNotifier.php — Créez un trait nommé EmailNotifier avec une méthode notify(string $message) qui retourne "Email: [message]".
  • SmsNotifier.php — Créez un trait nommé SmsNotifier avec une méthode notify(string $message) qui retourne "SMS: [message]".
  • AlertService.php — Créez une classe AlertService qui utilise les deux traits. Comme les deux traits possèdent une méthode notify(), vous devrez résoudre ce conflit :
    • Utilisez EmailNotifier::notify comme méthode notify() par défaut
    • Créez un alias notifyBySms pour la méthode SmsNotifier::notify
    Ajoutez également une méthode notifyAll(string $message) qui appelle les deux méthodes de notification et les retourne combinées sur des lignes séparées.
  • main.php — Incluez tous les fichiers nécessaires et créez une instance de AlertService. Vous recevrez une entrée : une chaîne de caractères pour le message. Affichez trois lignes :
    • Le résultat de l'appel à notify() avec le message
    • Le résultat de l'appel à notifyBySms() avec le message
    • Le résultat de l'appel à notifyAll() avec le message

Cela démontre comment insteadof résout quelle méthode de trait l'emporte en cas de conflit de nom, tandis que as vous permet de conserver l'accès à la méthode de l'autre trait sous un nom différent.

Aide-mémoire

Lorsque plusieurs traits définissent des méthodes portant le même nom, PHP nécessite une résolution de conflit explicite à l'aide des opérateurs insteadof et as.

L'opérateur insteadof sélectionne la méthode de quel trait utiliser par défaut :

<?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

L'opérateur as crée un alias pour une méthode de trait, permettant d'y accéder sous un nom différent.

Vous pouvez également utiliser as pour modifier la visibilité d'une méthode :

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

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

Essayez vous-même

<?php
require_once 'AlertService.php';

// Lire l'entrée
$message = trim(fgets(STDIN));

// TODO : Créer une instance de AlertService

// TODO : Afficher le résultat de l'appel à notify() avec le message

// TODO : Afficher le résultat de l'appel à notifyBySms() avec le message

// TODO : Afficher le résultat de l'appel à notifyAll() avec le message
?>
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet