Menu
Coddy logo textTech

Traits vs Héritage

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

Maintenant que vous comprenez comment fonctionnent les traits, clarifions quand utiliser les traits par rapport à l'héritage. Les deux permettent la réutilisation de code, mais ils servent des objectifs différents et ont des caractéristiques distinctes.

L'héritage établit une relation « est un ». Une classe Dog étendant Animal signifie qu'un chien est un animal. La classe enfant hérite de l'identité du parent et peut être utilisée partout où le type parent est attendu.

Les Traits fournissent une capacité « a un » (has-a). Lorsqu'une classe utilise un trait Loggable, elle possède une fonctionnalité de journalisation — mais elle ne devient pas un logger. Les traits ajoutent du comportement sans changer 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 :

AspectHéritageTraits
Relationest-un (is-a)possède une capacité (has-a)
LimiteParent unique seulementPlusieurs traits autorisés
Vérification de typeFonctionne avec instanceofPas d'identité de type
Idéal pourRelations hiérarchiquesComportements partagés entre classes non liées

Utilisez l'héritage lorsque les classes partagent une identité commune. Utilisez les traits lorsque des classes non liées ont besoin de la même fonctionnalité sans faire partie du même arbre généalogique.

challenge icon

Défi

Facile

Construisons un système de véhicules qui démontre quand utiliser l'héritage par rapport aux traits. Vous allez créer une hiérarchie de véhicules qui partagent une identité commune via l'héritage, tout en ajoutant des capacités transversales via des traits.

Vous organiserez votre code sur quatre fichiers :

  • Trackable.php — Créez un trait nommé Trackable qui fournit une capacité de suivi GPS. Le trait doit avoir :
    • Une propriété privée $location (string)
    • Une méthode setLocation(string $location) qui stocke l'emplacement actuel
    • Une méthode getLocation() qui retourne "Location: " . $this->location
    Ce trait représente une capacité de type « possède un » — n'importe quel véhicule peut avoir un suivi, mais avoir un suivi ne fait pas d'un objet un véhicule.
  • Vehicle.php — Créez une classe de base Vehicle qui établit la relation de type « est un ». Incluez le fichier du trait. Utilisez la promotion de constructeur pour définir une propriété protégée $brand. Ajoutez une méthode describe() qui retourne "Vehicle: " . $this->brand. Cette classe doit utiliser le trait Trackable car tous les véhicules de notre flotte auront un GPS.
  • Car.php — Créez une classe Car qui étend Vehicle. Incluez le fichier Vehicle. Utilisez la promotion de constructeur pour accepter la marque et une propriété privée $doors (integer). Appelez le constructeur parent avec la marque. Surchargez la méthode describe() pour retourner "Car: " . $this->brand . " with " . $this->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 de caractères pour l'emplacement. Créez une instance de Car, définissez son emplacement, puis affichez deux lignes :
    • Le résultat de l'appel à describe()
    • Le résultat de l'appel à getLocation()

Remarquez comment l'héritage et les traits fonctionnent ensemble ici : Car est un Vehicle (l'héritage établit l'identité), tandis que Vehicle possède une capacité de suivi (le trait ajoute un comportement). Vous pourriez utiliser instanceof Vehicle pour vérifier si un objet est un véhicule, mais il n'y a pas de type « Trackable » à vérifier — c'est la différence clé entre ces deux approches.

Aide-mémoire

Utilisez l'héritage pour les relations de type « est un » (is-a) et les traits pour les capacités de type « a une » (has-a).

L'héritage établit une identité : une classe enfant est un type de classe parente et peut être utilisée partout où le type parent est attendu.

Les traits ajoutent un comportement sans changer l'identité de la classe : une classe possède une fonctionnalité mais ne devient pas cette chose.

<?php
// Inheritance: Dog IS an Animal
class Animal {
    public function breathe(): void {
        echo "Breathing";
    }
}

class Dog extends Animal {
    public function bark(): void {
        echo "Woof!";
    }
}

// Trait: Cat HAS logging capability
trait Loggable {
    public function log(string $msg): void {
        echo "Log: $msg";
    }
}

class Cat extends Animal {
    use Loggable;
}
AspectHéritageTraits
Relationest un (is-a)a une capacité (has-a)
LimiteParent unique seulementPlusieurs traits autorisés
Vérification de typeFonctionne avec instanceofPas d'identité de type
Idéal pourRelations hiérarchiquesComportements partagés entre classes non liées

Utilisez l'héritage pour les relations hiérarchiques où les classes partagent une identité commune. Utilisez les traits pour les comportements partagés entre des classes non liées.

Essayez vous-même

<?php
// Fichier principal - créer et tester l'instance de 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 de Car avec la marque (brand) et les portes (doors)

// TODO: Définir l'emplacement (location) de la voiture

// TODO: Afficher le résultat de describe()

// TODO: Afficher le résultat de getLocation()
?>
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