Les traits en PHP
#1 Qu'est-ce qu'un trait ?
Les traits servent à partager du code entre des classes qui n'ont pas de relation hiérarchique entre elles.
Ci-dessous, j'ai besoin d'un morceau de code dans la classe qui est en bas à gauche et j'ai besoin du même morceau de code dans la classe qui est en haut à droite.
Et bien sûr, je ne veux pas dupliquer le code.
Il n'y a pas un ancêtre commun dans lequel on pourrait mettre ce code alors la solution, c'est le trait.
S'il y avait un ancêtre commun, on pourrait remonter ce code dans l'ancêtre et on n'aurait pas besoin d'un trait.
Un trait, il faut le voir comme un "include" sophistiqué, car il y a un mécanisme de gestion des collisions. Par collisions, je veux dire par exemple, un même nom de fonction dans deux traits. Avec des "include", on ne sait pas gérer. Avec des traits, on sait gérer.
#2 Déclarer et utiliser un trait
Pour déclarer un trait, vous utilisez le mot réservé trait
dans une structure qui ressemble à celle d'une classe ou d'une interface.
Vous lui donnez un nom qui contient le suffixe Trait de manière à respecter les PSRs.
Vous utilisez le trait dans une classe au moyen du mot réservé use
.
Le trait ne s'instancie pas.
#3 Incorporer plusieurs traits.
Vous pouvez incorporer plusieurs traits. Dans l'exemple ci-dessous, je déclare un deuxième trait BazTrait
. Puis, je déclare une méthode dans chaque trait. Enfin, j'instancie la classe et j'appelle les méthodes.
#4 Faire une hiérarchie de traits. Attention ... !
Ci-dessous, je déclare un trait QuxTrait
qui incorpore les deux traits BarTrait
et BazTrait
. Je n'ajoute pas de code dans QuxTrait
, mais je pourrais très bien. Rien ne l'interdit.
Vous voyez que je peux très bien construire une hiérarchie de traits. Ce qui peut être pratique, mais attention ! La programmation orientée objet consiste à concevoir une hiérarchie de classe, pas une hiérarchie de traits. Utilisez les traits juste quand il le faut.
#5 Gestion des collisions entre traits
Ci-dessous, je crée volontairement une collision en ajoutant la fonction fbigbang()
dans les deux traits BarTrait
et BazTrait
. Une erreur est levée seulement à l'exécution.
Je vais commencer par dire à php de choisir la fonction fbigbang
de BarTrait
. Pour cela, j'utilise un insteadof
.
Cela ne suffit pas, car maintenant, je voudrais pouvoir appeler la fbigbang
de BazTrait
. Pour cela, j'utilise un as
qui va renommer.
#6 Collision entre classes et traits
Ci-dessous, la classe Foo
étend la classe Fred
. A ce titre, elle hérite de la méthode fbar()
. La classe Foo
incorpore également le trait BarTrait
qui contient lui aussi une méthode fbar()
. La méthode fbar()
du trait est conservée. C'est logique puisqu'en étant incorporée dans Foo
, elle surcharge la méthode fbar()
de Fred
.
Ci-dessous, la classe Foo
contient une méthode fbar()
et importe celle du trait BarTrait
. C'est la méthode de la classe qui est conservée.