Les interfaces en PHP
#1 Qu'est-ce qu'une interface ?
Travailler avec une interface se fait en deux étapes :
- Dans la première étape, on procède à la déclaration de l'interface. Ci-dessous, la déclaration de l'interface
DataInterface
ne contient que la méthodegetQR()
. Ici, il n'y a que la signature de la méthode, c'est-à-dire sa "spécification". Il n'y a pas de corps. - Dans la deuxième étape, nous devons déclarer une classe qui procède à l'implémentation de l'interface. Ci-dessous, l'implémentation de l'interface
DataInterface
consiste à reprendre la signature de la méthodegetQR()
et à implémenter le corps de la méthode. Ici, je mets un simplereturn []
.
Il s'agit d'un contrat passé entre l'interface et la classe qui implémente l'interface. L'interface impose la signature et la classe a la liberté de l'implémentation. 😃
Le nom d'une interface doit se terminer par le suffixe Interface si vous voulez respecter les PSRs.
Ci-dessous, je résume les contraintes du contrat pour les deux parties :
- Les déclarations de méthodes de l'interface doivent être publiques.
- L'interface ne doit pas contenir de déclarations de propriétés.
- L'interface peut contenir des signatures de méthodes magiques. Notamment un constructeur.
- L'interface peut contenir des constantes.
- La classe doit respecter la signature. Ca veut dire qu'elle doit respecter :
- La visibilité.
- Le type des paramètres. Le nom d'un paramètre peut être différent.
- S'il y a une valeur par défaut dans l'interface, alors la classe doit en avoir une. Elle peut être différente.
- Le type de la valeur de retour.
- Une classe peut implémenter plusieurs interfaces.
- Plusieurs classes peuvent implémenter la même interface.
Si vous avez VSCode avec les bonnes extensions, il vous aidera pour respecter les signatures.
#2 Une classe peut implémenter plusieurs interfaces
Ci-dessous, la classe DataFic
implémente l'interface DataInterface
et l'interface ConfInterface
. Du coup, la classe DataFic
doit implémenter les deux signatures getQR()
et getConf()
.
Ce qu'il faut voir ici, c'est que vous ne pouvez pas faire cela avec deux classes abstraites (* à la place des deux interfaces). La classe fille ne pourrait pas hériter des deux classes mères étant donné que l'héritage multiple n'existe pas en PHP 🤭.
#3 Une interface peut être implémentée par plusieurs classes
Regardez ce que l'on peut faire avec cette possibilité 😀. Ci-dessous, j'ai déclaré une interface DataInterface
. Elle est implémentée de manière différente par deux classes FicData
et DbData
. FicData
va chercher les données sur fichier. DbData
va chercher les données en database.
Ensuite, je crée une classe PoserQuestion
qui a besoin qu'on lui injecte une interface. Je le spécifie dans le constructeur de PoserQuestion
en mettant un argument de type DataInterface
. Je peux, grâce aux interfaces, injecter (* dynamiquement si besoin) soit l'implémentation FicData
soit l'implémentation DbData
de DataInterface
😉. C'est possible de faire la même chose, en remplaçant l'interface par une classe abstraite qui contient une méthode abstraite getData()
. En fait, c'est le mécanisme de la signature et de son implémentation séparée qui permet de faire ça.