Aller au contenu principal

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.

Mais qu'est-ce qu'une interface ?

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.

astuce

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.

astuce

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.

astuce

Le polymorphisme permet à des objets de différentes classes d'être manipulés comme s'ils étaient des objets d'une même classe.

attention

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


Qu'est-ce qu'une interface en PHP ?


Quel est le rôle d'une interface ?


Une classe peut-elle implémenter plusieurs interfaces ?


Une interface peut-elle contenir des propriétés ?


Une classe qui implémente une interface doit-elle définir toutes les méthodes de cette interface ?



remarque

Dans une interface, toutes les méthodes doivent être public.

Pour en savoir plus sur les interfaces en PHP

astuce

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 et Magicien,
  • 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