Méthodes abstraites dans les Traits
Fait partie de la section Programmation Orientée Objet du Journey PHP de Coddy — leçon 54 sur 91.
Les traits peuvent fournir des méthodes prêtes à l'emploi, mais parfois vous avez besoin que la classe utilisant le trait implémente une fonctionnalité spécifique. C'est là que les méthodes abstraites dans les traits deviennent utiles - elles définissent un contrat que la classe utilisatrice doit remplir.
Lorsqu'un trait déclare une méthode abstraite, toute classe utilisant ce trait doit l'implémenter :
<?php
trait Notifiable {
abstract public function getEmail(): string;
public function sendNotification(string $message): void {
echo "Sending to " . $this->getEmail() . ": $message";
}
}
class User {
use Notifiable;
public function __construct(private string $email) {}
public function getEmail(): string {
return $this->email;
}
}
$user = new User("john@example.com");
$user->sendNotification("Welcome!");
Sortie :
Sending to john@example.com: Welcome!Le trait fournit la méthode sendNotification() mais s'appuie sur getEmail() pour être implémentée par la classe. Cela crée un modèle puissant où le trait gère la logique commune tout en déléguant les détails spécifiques à la classe à la classe d'implémentation.
Si une classe utilise le trait sans implémenter la méthode abstraite, PHP génère une erreur fatale. Cela garantit que les traits peuvent dépendre en toute sécurité de l'existence de certaines méthodes, rendant votre code plus prévisible et facile à maintenir.
Défi
FacileConstruisons un système de tarification où différents types de produits calculent leurs prix finaux différemment, mais partagent tous une logique de remise commune via un trait avec une méthode abstraite.
Vous organiserez votre code sur trois fichiers :
Discountable.php— Créez un trait appeléDiscountablequi fournit une fonctionnalité de remise. Le trait doit avoir :- Une méthode abstraite
getBasePrice(): floatque les classes utilisant ce trait doivent implémenter - Une méthode
applyDiscount(int $percent)qui calcule et retourne le prix après avoir appliqué le pourcentage de remise au prix de base - Une méthode
getFinalPrice(int $percent)qui retourne une chaîne formatée :"Final price: $[discounted_price]"avec 2 décimales
- Une méthode abstraite
Product.php— Créez une classeProductqui utilise le traitDiscountable. Incluez le fichier du trait. Utilisez la promotion de constructeur pour définir un$nameprivé (string) et un$priceprivé (float). Implémentez la méthodegetBasePrice()requise pour retourner le prix du produit.main.php— Incluez le fichier Product. Vous recevrez trois entrées : un nom de produit, un prix et un pourcentage de remise. Créez une instance deProductet affichez deux lignes :- Le prix de base formaté comme
"Base: $[price]"avec 2 décimales - Le résultat de l'appel à
getFinalPrice()avec le pourcentage de remise
- Le prix de base formaté comme
Ce modèle est puissant car le trait Discountable peut être utilisé par n'importe quelle classe — produits, services, abonnements — tant qu'elles implémentent getBasePrice(). Le trait fournit la logique de remise partagée tandis que chaque classe définit d'où provient son prix de base.
Aide-mémoire
Les traits peuvent déclarer des méthodes abstraites qui doivent être implémentées par toute classe utilisant le trait :
<?php
trait Notifiable {
abstract public function getEmail(): string;
public function sendNotification(string $message): void {
echo "Sending to " . $this->getEmail() . ": $message";
}
}
class User {
use Notifiable;
public function __construct(private string $email) {}
public function getEmail(): string {
return $this->email;
}
}
Le trait fournit des méthodes prêtes à l'emploi tout en exigeant que la classe implémente une fonctionnalité spécifique. Si une classe utilise le trait sans implémenter la méthode abstraite, PHP génère une erreur fatale.
Ce modèle permet aux traits de gérer la logique commune tout en déléguant les détails spécifiques à la classe implémentée.
Essayez vous-même
<?php
require_once 'Product.php';
// Lire les entrées
$name = trim(fgets(STDIN));
$price = floatval(trim(fgets(STDIN)));
$discountPercent = intval(trim(fgets(STDIN)));
// TODO: Créer une instance de Product avec le nom et le prix
// TODO: Afficher le prix de base formaté comme "Base: $[price]" avec 2 décimales
// TODO: Afficher le résultat de l'appel à getFinalPrice() avec le pourcentage de remise
?>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
1Les bases de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe mot-clé $thisMéthodesPropriétésConstructeur (__construct)Destructeur (__destruct)Récapitulatif - Calculatrice simple4Héritage
Héritage de baseLe mot-clé parent::Redéfinition de méthodeLe mot-clé finalClasses abstraitesRécapitulatif - Hiérarchie des employés7Encapsulation
Public, Protégé, PrivéModificateurs d'accès en détailGetters et SettersMasquage d'informationPromotion de constructeur (8.0)Récapitulatif - Système de gestion d'étudiants10Concepts avancés de la POO
Composition vs HéritageInjection de dépendancesClasses anonymesÉnumérations (PHP 8.1)Fibers (PHP 8.1)Clonage d'objets : analyse approfondieGénérateurs et Itérateurs13Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository2Espaces de noms et Autoloading
Introduction aux espaces de nomsLe mot-clé useStandard d'Autoloading PSR-4L'Autoloader ComposerRécapitulatif - Projet organisé5Interfaces et Contrats
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesInterface vs Classe AbstraiteType Hinting avec les InterfacesRécapitulatif - Calculateur de Formes8Méthodes magiques
Introduction aux méthodes magiques__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Clonage d'objets__serialize & __unserializeRécapitulatif - Collection personnalisée3Propriétés de classe
Propriétés d'instance vs Propriétés statiquesConstantes dans les classesMéthodes et propriétés statiquesPropriétés privées et protégéesPropriétés readonly (PHP 8.1)Récapitulatif - Gestionnaire de compte bancaire6Polymorphisme
Retour sur la redéfinition de méthodePolymorphisme via les interfacesType Hinting et Types d'unionLiaison statique tardiveRécapitulatif - Processeur de paiement9Traits
Introduction aux TraitsUtilisation de plusieurs TraitsRésolution des conflits de TraitsMéthodes abstraites dans les TraitsTraits vs Héritage12Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie