Easy-Micro

LANGAGE Intro POO PHP
Interface

Introduction à la programmation orientée objet en PHP

Interface

Les interfaces vont avoir un but similaire aux classes abstraites puisque l'un des intérêts principaux liés à la définition d'une interface va être de fournir un plan général pour les développeurs qui vont implémenter l'interface et de les forcer à suivre le plan donné par l'interface.

Les deux différences majeures entre les interfaces et les classes abstraites sont :

1. Une interface ne peut contenir que les signatures des méthodes (c'est-à-dire le nom et les paramètres) ainsi qu'éventuellement des constantes mais pas de propriétés. Cela est dû au fait qu'aucune implémentation n'est faite dans une interface : une interface n'est véritablement qu'un plan ;

2. Une classe ne peut pas étendre plusieurs autres classes à cause des problèmes d'héritage. En revanche, une classe peut tout à fait implémenter plusieurs interfaces.

Le problème du diamant

Pourquoi une classe n'a pas l'autorisation d'étendre plusieurs autres classes? Pour cela, imaginons qu'on ait une première classe A qui définit la signature d'une méthode diamond() sans l'implémenter. Nous créons ensuite deux classes B et C qui étendent la classe A et qui implémentent chacune d'une manière différente la méthode diamond(). Finalement, on crée une classe D qui étend les classes B et C et qui ne redéfinit pas la méthode diamond(). Dans ce cas-là, on est face au problème suivant : la classe D doit-elle utiliser l'implémentation de diamond() faite par la classe B ou celle faite par la classe C ?

Le fichier classes/utilisateur.interface.php
<?php
interface Utilisateur{
     public const ABONNEMENT = 15;
     public function getNom();
     public function setPrixAbo();
     public function getPrixAbo();
}
On va pouvoir définir une interface de la même manière qu'une classe mais en utilisant cette fois-ci le mot clef interface à la place de class

On va ensuite pouvoir réutiliser les définitions de notre interface dans des classes. Pour cela, on va implémenter notre interface. On va pouvoir faire cela de la même manière que lors de la création de classes étendues mais on va cette fois-ci utiliser le mot clef implements à la place de extends

Le fichier classes/admin.class.php
<?php
class Admin implements Utilisateur {
     protected $user_name;
     protected $user_region;
     protected $prix_abo;
     protected $user_pass;
     protected static $ban;
        
     public function __construct($n, $p, $r) {
         $this->user_name = strtoupper($n);
         $this->user_pass = $p;
         $this->user_region = $r;
     }
        
     public function getNom() {
         echo $this->user_name;
      }
     public function getPrixAbo() {
         echo $this->prix_abo;
     }
        
     public function setBan(...$b) {
         foreach($b as $banned){
             self::$ban[] .= $banned;
         }
     }
     public function getBan() {
        echo 'Utilisateurs bannis : ';
         foreach(self::$ban as $valeur) {
             echo $valeur .', ';
         }
     }
        
     public function setPrixAbo() {
         if($this->user_region === 'Sud'){
             // parent est remplacé par le nom de l'interface
             return $this->prix_abo = Utilisateur::ABONNEMENT / 6;
         } else {
             // parent est remplacé par le nom de l'interface
             return $this->prix_abo = Utilisateur::ABONNEMENT / 3;
         }
     }
}
Le fichier classes/abonne.class.php
<?php
class Abonne implements Utilisateur {
     protected $user_name;
     protected $user_region;
     protected $prix_abo;
     protected $user_pass;
        
     public function __construct($n, $p, $r) {
         $this->user_name = $n;
         $this->user_pass = $p;
         $this->user_region = $r;
     }
        
     public function getNom() {
         echo $this->user_name;
     }
     public function getPrixAbo() {
         echo $this->prix_abo;
     }
        
     public function setPrixAbo() {
         if($this->user_region === 'Sud') {
             // parent est remplacé par le nom de l'interface
             return $this->prix_abo = Utilisateur::ABONNEMENT / 2;
         } else {
             // parent est remplacé par le nom de l'interface
             return $this->prix_abo = Utilisateur::ABONNEMENT;
         }
     }
}

Vous pouvez également observer que pour accéder à une constante d'interface, il va falloir préciser le nom de l'interface devant l'opérateur de résolution de portée.

Le fichier index.php
<!DOCTYPE html>
<html  lang="fr">
<head>
<title>POO PHP</title>
<meta charset="utf-8">
<link rel="stylesheet" href="css/mesStyles.css">
</head>
<body>
<h1>Inscription</h1>
<?php
     require 'classes/utilisateur.interface.php';
     require 'classes/admin.class.php';
     require 'classes/abonne.class.php';

     $Admin1 = new Admin('Pierre', 'abcdef', 'Sud');
     $Admin2 = new Admin('Mathilde', 123456, 'Nord');
     $Abonne1 = new Abonne('Edouard', 123456, 'Est');
        
     $Admin1 -> setPrixAbo();
     $Admin2 -> setPrixAbo();
     $Abonne1 -> setPrixAbo();

     echo 'Prix de l\'abonnement pour ';
     $Admin1 -> getNom();
     echo ' : ';
     $Admin1 -> getPrixAbo();

     echo '<br>Prix de l\'abonnement pour ';
     $Admin2 -> getNom();
     echo ' : ';
     $Admin2 -> getPrixAbo();

     echo '<br>Prix de l\'abonnement pour ';
     $Abonne1 -> getNom();
     echo ' : ';
     $Abonne1 -> getPrixAbo();
?>
</body>
</html>

-> Voir cet exemple Easy-Micro

Les interfaces prédéfinies

De la même manière qu’il existe des classes prédéfinies, c'est-à-dire des classes natives ou encore prêtes à l'emploi en PHP, nous allons pouvoir utiliser des interfaces prédéfinies.

Parmi celles-ci, nous pouvons notamment noter :

  • L'interface Traversable dont le but est d'être l'interface de base de toutes les classes permettant de parcourir des objets;
  • L'interface Iterator qui définit des signatures de méthodes pour les itérateurs;
  • L'interface IteratorAggregate qui est une interface qu'on va pouvoir utiliser pour créer un itérateur externe;
  • L'interface Throwable qui est l'interface de base pour la gestion des erreurs et des exceptions;
  • L'interface ArrayAccess qui permet d'accéder aux objets de la même façon que pour les tableaux;
  • L'interface Serializable qui permet de personnaliser la linéarisation d'objets.

Nous n'allons pas étudier ces interfaces en détail ici. Cependant, nous allons en utiliser certaines dans les parties à venir et notamment nous servir de Throwable et des classes dérivées prédéfinies Error et Exception dans la partie liée à la gestion des erreurs et des exceptions.


Flux RSS Easy-Micro - Abonnez-vous Easy-Micro [ François Bisch ]