Médiaforma

All posts tagged polymorphisme

La notion de polymorphisme est assez abstraite et peu utile en PHP. Elle découle de la notion d’héritage. Supposons qu’une classe Laser et trois classes dérivées CD, DVD et Blue aient été définies. Les trois classes dérivées ont toutes les caractéristiques de la classe Laser. Ainsi, des objets de type CD, DVD et Blue peuvent être traités comme des objets de type Laser. Cependant, il est possible de surcharger les méthodes d’instance de la classe parente afin d’induire des comportements spécifiques aux classes dérivées.

class Laser {
  public function caracteristiques() {
    echo "Disque laser<br>";
  }
}
class CD extends Laser{
  public function caracteristiques() {
    parent::caracteristiques();
    echo "Capacité : 700 Mo<br>";
  }
}
class DVD extends Laser {
  public function caracteristiques() {
    parent::caracteristiques();
    echo "Capacité : 4,7 Go<br>";
  }
}
class Blue extends Laser {
  public function caracteristiques() {
    parent::caracteristiques();
    echo "Capacité : 25 Go<br>";
  }
}

Sans entrer dans le détail du code, vous pouvez comprendre que les classes héritées CD, DVD et Blue surchargent la méthode publique caracteristiques de la classe parente laser. Elles conservent le comportement de la méthode parente (parent::caracteristiques();) et la complètent avec des informations qui leur sont spécifiques.


La programmation orientée objet (POO) a essentiellement deux avantages. Elle :

  • facilite l’organisation du code et donc le développement ;
  • permet de définir des modules réutilisables.

La programmation orientée objets repose sur trois notions fondamentales : l’encapsulation, l’héritage et le polymorphisme.

Les classes définissent des structures composées de variables et de fonctions. Pour utiliser les termes propres à la POO, les variables d’une classe sont appelées propriétés. Quant aux fonctions de la classe, elles sont appelées méthodes.

Les instances, c’est-à-dire les utilisations d’un type classe, sont appelées des objets. Les variables et fonctions d’une classe sont appelés composants ou membres de la classe.

Si vous avez du mal à vous y retrouver avec tous ces nouveaux termes, nous allons faire une analogie. Considérez une classe comme une usine qui fabrique des voitures. Les instances de l’usine (la classe) sont des voitures (les objets). La cylindrée, la couleur, le type des pneus, etc. sont des caractéristiques (propriétés) propres à chaque voiture. Selon les caractéristiques des voitures à fabriquer, il faut appliquer différents procédés de fabrication (méthodes).


Les classes abstraites sont utilisées pour définir des méthodes qui dépendent d’autres méthodes dont le code n’est pas défini dans la classe. Ici par exemple, la méthode rapport() fait appel aux méthodes abstraites perimetre() et surface(). Seule leur signature est définie dans la classe abstraite :

public abstract class Forme {
   public abstract float perimetre(); //methode abstraite
   public abstract float surface(); //methode abstraite

   public double rapport() {
      return surface() / perimetre();
   }
}

Nous pourrions par exemple créer une classe Cercle qui étend la classe Forme, qui définit les deux méthodes abstraites (perimetre() et surface()) de la classe Forme et qui surcharge la méthode toString de java.lang.Object :

public class Cercle extends Forme {
   private int rayon;

   public Cercle(int r) {
      this.rayon=r;
   }

   public float perimetre() {
      float resultat = 2 * (float)Math.PI * rayon;
      return resultat;
   }

   public float surface() {
      return (float)Math.PI * rayon * rayon;
   }

   public String toString() {
      return ("un cercle de rayon " + rayon);
   }
}

De la même manière, nous pourrions définir la classe Rectangle() qui étend la classe Forme, qui définit les deux méthodes abstraites (perimetre() et surface()) de la classe Forme et qui surcharge la méthode toString de java.lang.Object :

public class Rectangle extends Forme {
  private int longueur, largeur;

  public Rectangle(int longueur, int largeur) {
    this.longueur = longueur;
    this.largeur = largeur;
  }

  public float perimetre() {
     return 2 * (longueur + largeur);
  }

  public float surface() {
     return longueur * largeur;
  }

  public String toString() {
    return ("un rectangle de longueur " + longueur + " et de largeur " + largeur);
  }
}

Voici un exemple d’utilisation des sous-classes de Forme :

class EssaiFormes {

  public static void main(String[] arg) { 

      Cercle = new Cercle(2);

      Rectangle = new Rectangle(2, 1);

     

      System.out.printf("Rapport Surface/Périmètre pour " + cercle + ": %.3f\n", cercle.rapport());

      System.out.printf("Rapport Surface/Périmètre " + rectangle + " : %.3f\n", rectangle.rapport());

  }

}

Voici le résultat :

 

Essayez ce code et vérifiez son fonctionnement.