Traits par rapport à l’héritage
Fait partie de la section Programmation Orientée Objet du Journey PHP de Coddy. Leçon 55 sur 91.
Maintenant que tu comprends le fonctionnement des traits, clarifions quand utiliser les traits plutôt que l’héritage. Les deux permettent de réutiliser du code, mais ils répondent à des objectifs différents et possèdent des caractéristiques distinctes.
L’héritage établit une relation « est-un ». Une classe Dog qui étend Animal signifie qu’un chien est un animal. La classe enfant hérite de l’identité de la classe parente et peut être utilisée partout où le type parent est attendu.
Les traits fournissent une capacité « possède-un ». Lorsqu’une classe utilise le trait Loggable, elle possède une fonctionnalité de journalisation — mais elle ne devient pas un enregistreur. Les traits ajoutent un comportement sans modifier ce qu’est fondamentalement la classe.
<?php
// Héritage : Dog EST un Animal
class Animal {
public function breathe(): void {
echo "Breathing";
}
}
class Dog extends Animal {
public function bark(): void {
echo "Woof!";
}
}
// Trait : Dog A une capacité de journalisation
trait Loggable {
public function log(string $msg): void {
echo "Log: $msg";
}
}
class Cat extends Animal {
use Loggable;
}
Différences clés à retenir :
| Aspect | Héritage | Traits |
|---|---|---|
| Relation | est-un | possède une capacité |
| Limite | Un seul parent | Plusieurs traits autorisés |
| Vérification de type | Fonctionne avec instanceof | Aucune identité de type |
| Idéal pour | Les relations hiérarchiques | Les comportements partagés entre des classes sans lien |
Utilisez l’héritage lorsque les classes partagent une identité commune. Utilisez les traits lorsque des classes sans lien ont besoin de la même fonctionnalité sans faire partie du même arbre généalogique.
Défi
FacileConstruisons un système de véhicules qui montre quand utiliser l’héritage plutôt que les traits. Vous allez créer une hiérarchie de véhicules qui partagent une identité commune grâce à l’héritage, tout en ajoutant des fonctionnalités transversales grâce aux traits.
Vous organiserez votre code sur quatre fichiers :
Trackable.php: créez un trait appeléTrackablequi fournit une fonctionnalité de suivi GPS. Le trait doit avoir :- Une propriété privée
$location(chaîne de caractères) - Une méthode
setLocation(string $location)qui stocke la position actuelle - Une méthode
getLocation()qui renvoie"Location: [location]"
- Une propriété privée
Vehicle.php: créez une classe de baseVehiclequi établit la relation "is-a". Incluez le fichier du trait. Utilisez la promotion du constructeur pour définir une propriété protégée$brand. Ajoutez une méthodedescribe()qui renvoie"Vehicle: [brand]". Cette classe doit utiliser le traitTrackable, puisque tous les véhicules de notre flotte disposeront du GPS.Car.php: créez une classeCarqui étendVehicle. Incluez le fichier Vehicle. Utilisez la promotion du constructeur pour accepter la marque et une propriété privée$doors(entier). Appelez le constructeur parent avec la marque. Remplacez la méthodedescribe()pour qu’elle renvoie"Car: [brand] with [doors] doors".main.php: incluez le fichier Car. Vous recevrez trois entrées : un nom de marque, un nombre de portes et une chaîne représentant une position. Créez une instance deCar, définissez sa position, puis affichez deux lignes :- Le résultat de l’appel à
describe() - Le résultat de l’appel à
getLocation()
- Le résultat de l’appel à
Remarquez comment l’héritage et les traits fonctionnent ici ensemble : Car is a Vehicle (l’héritage établit l’identité), tandis que Vehicle has une fonctionnalité de suivi (le trait ajoute un comportement). Vous pourriez utiliser instanceof Vehicle pour vérifier si quelque chose est un véhicule, mais il n’existe aucun type "Trackable" contre lequel effectuer la vérification : c’est la différence essentielle entre ces deux approches.
Essayez vous-même
<?php
// Fichier principal - créer et tester l'instance Car
// TODO: Inclure le fichier Car.php
// Lire les entrées
$brand = trim(fgets(STDIN));
$doors = intval(trim(fgets(STDIN)));
$location = trim(fgets(STDIN));
// TODO: Créer une instance Car avec brand et doors
// TODO: Définir l'emplacement de la voiture
// TODO: Afficher le résultat de describe()
// TODO: Afficher le résultat de getLocation()
?>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
1Fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses et objetsLe mot-clé $thisMéthodesPropriétésConstructeur (__construct)Destructeur (__destruct)Récapitulatif - Calculatrice simple4Héritage
Héritage de baseLe mot-clé parent::Redéfinition des méthodesLe mot-clé finalClasses abstraitesRécapitulatif – Hiérarchie des employés7Encapsulation
Public, Protected, PrivateModificateurs d’accès en profondeurAccesseurs et mutateursDissimulation de l’informationPromotion des constructeurs (8.0)Récapitulatif – Système de fiches étudiant10Concepts avancés de la POO
Composition ou héritageInjection de dépendancesClasses anonymesÉnumérations (PHP 8.1)Fibres (PHP 8.1)Approfondissement du clonage d’objetsGénérateurs et itérateurs13Patrons de conception – Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode modèlePatron ÉtatPatron CompositePatron Dépôt2Espaces de noms et chargement automatique
Introduction aux espaces de nomsLe mot-clé useNorme de chargement automatique PSR-4Autoloader de ComposerRécapitulatif - Projet organisé5Interfaces et contrats
Introduction aux interfacesImplémentation des interfacesImplémentation de plusieurs interfacesInterface ou classe abstraiteIndication de type avec les interfacesRécapitulatif - Calculateur de formes8Méthodes magiques
Introduction aux méthodes magiques__toString et __debugInfo__get, __set, __isset, __unset__call et __callStatic__clone et clonage d’objets__serialize et __unserializeRécapitulatif - Collection personnalisée3Propriétés de classe
Propriétés d’instance vs statiquesConstantes dans les classesMéthodes et propriétés statiquesPropriétés privées et protégéesPropriétés en lecture seule (PHP 8.1)Récapitulatif - Gestionnaire de comptes bancaires6Polymorphisme
Révision de la redéfinition des méthodesPolymorphisme via les interfacesAnnotations de type et types unionLiaison statique tardiveRécapitulatif - Processeur de paiements9Traits
Introduction aux traitsUtilisation de plusieurs traitsRésolution des conflits entre traitsMéthodes abstraites dans les traitsTraits par rapport à l’héritage12Patrons de conception – Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FactoryPatron ObserverPatron StrategyEntraînez-vous par vous-même : Compilateur PHP en ligne