Le polymorphisme
Notions théoriques
Le polymorphisme est la capacité d'une variable, d'une fonction ou d'un objet d'avoir plusieurs formes.
En POO, le polymorphisme se manifeste par :
- l'héritage de classes
- et l'implémentation d'interfaces.
Nous avons vu ce qu'est l'héritage.
Par exemple, si vous avez une classe parente Animal
et des classes enfants Chien
et Chat
, une variable de type Animal
pourrait se référer à une instance de Chien
ou de Chat
.
Cela signifie que vous pouvez traiter des objets de différentes classes de la même manière, tant qu'ils héritent d'une classe commune.
Une interface est un ensemble de signatures.
Qu'est-ce qu'une signature ?
Une signature = le nom de la méthode + les paramètres avec leurs types + le type de retour
Voici un exemple de signature dans une interface Combattant
:
interface Combattant {
public function attaquer(Combattant $adversaire): int;
}
Dans cet exemple, attaquer
est une méthode qui prend un paramètre de type Combattant
(l'adversaire à attaquer) et renvoie un int
(les dégâts infligés à l'adversaire).
Maintenant, toute classe qui implémente Combattant
doit fournir une implémentation de la méthode attaquer
. Par exemple :
class Guerrier implements Combattant {
public function attaquer(Combattant $adversaire): int {
// Code pour attaquer l'adversaire...
// Retourne les dégâts infligés.
return $degats;
}
}
Dans cet exemple, la classe Guerrier
respecte le "contrat" défini par l'interface Combattant
en fournissant une implémentation de la méthode attaquer
.
Les méthodes dans une interface n'ont pas de corps ; elles sont déclarées, mais pas implémentées.
Chaque méthode déclarée dans une interface est une signature.
C'est la responsabilité de chaque classe qui implémente l'interface de fournir une implémentation pour chacune de ces méthodes.
C'est pourquoi on dit souvent qu'une interface définit un contrat que les classes doivent respecter.
Ce contrat stipule que toute classe qui implémente l'interface doit fournir une implémentation pour chaque méthode déclarée dans l'interface.
Par exemple, si vous avez une interface Soignable
avec une méthode seSoigner
, toute classe qui implémente Soignable
doit fournir une implémentation pour la méthode seSoigner
.
Une interface est utilisée pour représenter une capacité : "être capable de".
Les interfaces sont utiles pour garantir que différentes classes suivent la même structure, même si elles n'héritent pas d'une classe commune.
Cela facilite l'interchangeabilité des objets.
Le polymorphisme permet à des objets de différentes classes d'être manipulés comme s'ils étaient des objets d'une même classe.
Le polymorphisme est un concept fondamental en programmation orientée objet (POO).
Exemple pratique
Poursuivons avec notre jeu de combat. Imaginons que nous voulons introduire une nouvelle fonctionnalité : certains personnages peuvent se seSoigner. Pour cela, nous allons créer une interface Soignable
avec une méthode seSoigner
.
interface Soignable {
public function seSoigner();
}
class Guerrier extends Personnage {
// ...
public function attaquer() {
echo $this->getNom() . " attaque avec une force de " . $this->force . " points.\n";
}
}
class Magicien extends Personnage implements Soignable {
// ...
public function attaquer() {
echo $this->getNom() . " lance un sort avec un niveau de magie de " . $this->magie . " points.\n";
}
public function seSoigner() {
$this->setPointsDeVie($this->getPv() + $this->magie);
echo $this->getNom() . " se soigne et récupère " . $this->magie . " points de vie.\n";
}
}
Dans cet exemple, la fonction seSoigner
peut accepter n'importe quel objet qui implémente l'interface Soignable
, peu importe sa classe exacte.
function soignerPersonnage(Soignable $personnage) {
$personnage->seSoigner();
}
$magicien = new Magicien();
$pretre = new Pretre();
soignerPersonnage($magicien); // Le magicien se soigne
soignerPersonnage($pretre); // Le prêtre se soigne
C'est le polymorphisme en action : différentes classes (Magicien
, Pretre
) sont traitées de la même manière grâce à l'interface Soignable
qu'elles implémentent.
Test de mémorisation/compréhension
Dans une interface, toutes les méthodes doivent être public
.
Pour en savoir plus sur les interfaces en PHP
Une classe PHP peut implémenter plusieurs interfaces :
class Guerrier extends Personnage implements Soignable, Voleur
{
/* ... */
}
TP pour réfléchir et résoudre des problèmes
Pour ce TP, nous allons nous inspirer de l'exemple pratique.
Vous allez devoir implémenter une interface dans notre jeu de combat.
Dans le répertoire classes
du répertoire jeu_combat
(de la séance précédente),
vous allez créer une interface Soignable
avec une méthode seSoigner
.
La classe Magicien
implémentera cette interface et définira la méthode seSoigner
.
Enfin, testez votre code** :
- en créant des instances des classes
Guerrier
etMagicien
, - en définissant leurs propriétés,
- en appelant la méthode
attaquer
- et en appelant la méthode
seSoigner
du magicien.
Voici le code qui sera saisi dans le fichier main.php
:
$guerrier = new Guerrier();
$guerrier->setNom("Arthur");
$guerrier->setPointsDeVie(100);
$guerrier->setExperience(0);
$guerrier->setForce(50);
$guerrier->attaquer(); // Affiche "Arthur attaque avec une force de 50 points."
$magicien = new Magicien();
$magicien->setNom("Merlin");
$magicien->setPointsDeVie(80);
$magicien->setExperience(0);
$magicien->setMagie(100);
$magicien->attaquer(); // Affiche "Merlin lance un sort avec un niveau de magie de 100 points."
$magicien->seSoigner();
Une solution
Vous devez être connecté pour voir le contenu.