IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Utilisation des interfaces en PHP

Date de publication : 12.03.2006

Par Alain Sahli
 

Cet article traite l'utilisation des interfaces en PHP. Ce dernier n'est pas destiné à des débutants et de bonnes bases en POO sont requises pour la compréhension du code fourni tout au long de l'article.

I. Introduction
II. Les interfaces
II-A. Création
II-B. Implémentation
II-B-1. Implémentation d'une interface
II-B-2. Implémentation de plusieurs interfaces
III. Exemple d'utilisation
III-A. Pré-requis
III-B. Arborescence de l'exemple
III-C. L'interface IAnimal.php
III-D. Les classes
III-D-1. La classe Zoo
III-D-2. La classe Lion
III-D-3. La classe Gazelle
III-E. Le fichier autoload.inc.php
III-F. Résultat final
IV. Les interfaces existantes
V. Conclusion


I. Introduction

Contrairement à PHP4, PHP5 permet de gérer les interfaces. Ces-dernières permettent de créer un modèle, que les classes qui l'implémentent doivent respecter. On peut comparer une interface à une fiche éléctrique, elle définit un standard de "connexion" sans savoir quelles types d'appareils vont venir s'y connecter. Les interfaces sont très pratiques lorsque plusieurs personnes développent un même projet, ou lorsqu'on développe un site modulaire.


II. Les interfaces

Une interface regroupe toutes les méthodes qu'une classe doit contenir pour l'implémenter. Ce procédé permet d'appeler les méthodes d'une classe sans se soucier de l'existence de ces dernières. Les méthodes déclarées dans une interface ne peuvent être de type private étant donné que l'on définit dans une interface les méthodes que l'on pourra appeler lors de l'instanciation. Déclarer des fonctions private reviendrait à imposer un style de traitement dans la classe alors que ce n'est pas le but.


II-A. Création

Pour créer une interface on procède de la même manière que lorsqu'on crée une classe mais à la place d'utiliser le mot clé "class", on utilise le mot clé "interface".
Création d'une interface

<?php
interface IMonInterface 
{  
    public function titi($name);  
    public function toto($firstName); 
}  

interface IMonInterfaceStatic 
{  
	static function staticTiti($name);  
	static function staticToto($firstName); 
} 
?>

II-B. Implémentation

L'implémentation se fait de la même manière que l'héritage, sauf que l'on utilise le mot clé "implements". Une classe peut implémenter plusieurs interfaces. Quand une classe implémente une interface, cela signifie que toutes les méthodes présentes dans l'interface le sont également dans la classe!

warning Si une classe implémente une interface et ne contient pas toutes les méthodes déclarées dans celle-ci, une erreur sera générée!

II-B-1. Implémentation d'une interface

Comme vous pouvez le voir ci-dessous j'ai simplement déclaré une classe "MaClasse" qui implémente l'interface "IMonInterface". Ensuite il a fallu créer toutes les méthodes présentent dans l'interface.
Implémentation d'une interface

<?php
require_once 'IMonInterface.php';  
class MaClasse implements IMonInterface 
{   
	public function titi($name)  
	{   
		echo $name;  
	}
	   
	public function toto($firstName)  
	{   
		echo $firstName;  
	} 
} 
?>

II-B-2. Implémentation de plusieurs interfaces

Lorsqu'une classe implémente plusieurs interfaces, il faut les séparer par une ',' (virgule). La classe ci-dessous implémente deux interfaces; il a donc fallu créer toutes les méthodes contenues dans l'interface "monInterface" ainsi que toutes les méthodes présentes dans l'interface "monInterfaceStatic".
Implémentation de plusieurs interfaces

<?php
require_once 'IMonInterface.php'; 
require_once 'IMonInterfaceStatic.php'; 
 
class MaClassMultiInterfaces implements IMonInterface, IMonInterfaceStatic 
{  
    public function titi($name)  
	{   
		echo $name;  
	}    
	
	public function toto($firstName)  
	{   
		echo $firstName;  
	}    
	
	static function staticTiti($name)  
	{   
		echo $name;  
	}    
	
	static function staticToto($firstName)  
	{   
		echo $firstName;  
	} 
} 
?>
warning Lors de l'implémentation de plusieurs interfaces, il faut faire attention de ne pas créer les mêmes noms de méthodes dans plusieurs interfaces!

III. Exemple d'utilisation

Nous sommes maintenant capables de créer et d'implémenter des interfaces. Réalisons un exemple concret.
Imaginons une classe Zoo.php qui va devoir afficher un inventaire de tous ses animaux avec leur nourriture préférée. Nous savons que la classe Zoo.php devra appeler trois méthodes: getAnimal(), getNourriture() et getNom() mais nous ne savons pas combien d'animaux il y aura. Pour cela nous allons créer une interface IAnimal que chaque animal devra implémenter pour pouvoir entrer dans le Zoo.


III-A. Pré-requis

Pour réaliser cet exemple il est nécessaire d'avoir au minimum la version 5 de PHP.

info Les essais on été fait avec la version 5.2.0

III-B. Arborescence de l'exemple

Ci-dessous l'arborescence du projet:
index.php
/class
   Gazelle.php
   Lion.php
   Zoo.php
/interface
   IAnimal.php
/inc
   autload.inc.php


III-C. L'interface IAnimal.php

Comme je l'ai expliquer dans la partie "Exemple d'utilisation" toutes les classes d'animaux devront pouvoir nous retourner l'animal concerné, la nourriture qu'il mange ainsi que sont nom. Nous allons créer ces trois méthodes dans notre interface.
Interface IAnimal.php

<?php
interface IAnimal
{
	// Retourne le type d'animal
	public function getAnimal();
	
	// Retourne la nourriture qu'il mange
	public function getNourriture();
	
	// Retourne le nom de l'animal
	public function getName();
}
?>

III-D. Les classes

Pour illustrer cet exemple nous allons donc créer 3 classes, une classe Zoo qui est la classe mère et deux classes d'animaux (Lion et Gazelle).


III-D-1. La classe Zoo

Class Zoo

<?php
class Zoo
{	
	public function showAnimals()
	{
		// Tableau contenant les animaux
		$animaux = array();
		
		// On ajoute les animaux dans le tableau
		$animaux[]($animaux, new Lion('Bobby'));
		$animaux[]($animaux, new Gazelle('Petra'));
		
		// On traite tous les animaux contenus dans le tableau $animaux
		foreach($animaux as $animal)
		{
			echo 'Animal: '.$animal->getAnimal().'<br/>';
			echo 'Nom: '.$animal->getName().'<br/>';
			echo 'Nourriture préférée: '.$animal->getNourriture().'<br/><br/>';
		}
	}
}
?>

III-D-2. La classe Lion

Classe Lion

<?php
require_once 'interface/IAnimal.php';

class Lion implements IAnimal
{
	private $name;
	
	public function __construct($argName)
	{
		$this->name = $argName;
	}
	
	public function getAnimal()
	{
		return 'Lion';
	}
	
	public function getNourriture()
	{
		return 'Viande';
	}
	
	public function getName()
	{
		return $this->name;
	}
}
?>

III-D-3. La classe Gazelle

Classe Gazelle

<?php
require_once 'interface/IAnimal.php';

class Gazelle implements IAnimal
{
	private $name;
	
	public function __construct($argName)
	{
		$this->name = $argName;
	}
	
	public function getAnimal()
	{
		return 'Gazelle';
	}
	
	public function getNourriture()
	{
		return 'Herbe';
	}
	
	public function getName()
	{
		return $this->name;
	}
}
?>

III-E. Le fichier autoload.inc.php

Ce fichier contient la fonction __autoload() qui est appelée lorsqu'on instancie une classe et que le fichier de classe n'est pas inclu. Cette fonction va donc s'occuper de charger les classes.
autoload.inc.php

<?php
function __autoload($className)
{
	require_once('class/'.$className.'.php');
}
?>

III-F. Résultat final

Maintenant que tous ces fichiers sont créés il nous faut encore créer l'index.php qui va afficher les animaux du zoo.
Fichier index.php

<?php
require_once 'inc/autoload.inc.php';

$Zoo = new Zoo();
$Zoo->showAnimals();
?>
Et voici ce que sa affiche:

Animal: Lion
Nom: Bobby
Nourriture préférée: Viande

Animal: Gazelle
Nom: Petra
Nourriture préférée: Herbe

IV. Les interfaces existantes

Peut être l'aurai vous déjà remarqué, lorsqu'on utilise la fonction get_declared_interfaces() PHP va vous retourner le tableau suivant:
Array
(
    [0] => Traversable
    [1] => IteratorAggregate
    [2] => Iterator
    [3] => ArrayAccess
    [4] => reflector
    [5] => RecursiveIterator
    [6] => SeekableIterator
}
Ce sont des interfaces prédéfinies par PHP. Etant donné qu'un exemple est mille fois plus parlant que des lignes de texte je vais vous donner un exemple concret. Imaginez que vous aimeriez avoir un tableau qui ne supporte pas les clés de type 'string'. Vous savez que c'est impossible car PHP est très souple au niveau des tableaux et il accepte les clés de type 'string'.
Pour remédier à ce problème, nous allons créer notre propre classe de gestion de tableau qui ne va accepter que les clés de type 'int'.
Gestion de tableau

<?php
class MyArray implements ArrayAccess
{
    protected $array = array();
    
    // Méthode d'ajout d'une valeur dans le tableau
    function offsetSet($offset, $value)
    {
    	if(!is_numeric($offset))
    	{
    		throw new Exception('Clé invalide!');
    	}
    	$this->array[$offset] = $value;
    }
    
    // Retourne une valeur contenue dans le tableau
    public function offsetGet($offset)
    {
    	return $this->array[$offset];
    }
    
    // Supprime une valeur du tableau
    public function offsetUnset($offset)
    {
    	unset($this->array[$offset]);
    }
    
    // Test si une valeur existe dans le tableau
    public function offsetExists($offset)
    {
    	return isset($this->array[$offset]);
    }
}

$myArray = new MyArray();
$myArray['a'] = 10; // va générer une exception 'Clé invalide'
$myArray[3] = 12;
?>
Les quatres méthodes qui sont présentes dans la classe MyArray sont obligatoires! Ce n'est pas moi qui ai choisi de les implémenter, c'est l'interface ArrayAccess qui m'oblige à les implémenter pour garantir le bon fonctionnement de mon tableau. Chaque interface a ces propres fonctions, je vous laisse les découvrir ici : SPL.


V. Conclusion

A première vue, les interfaces ont l'air inutiles mais lorsqu'on développe de gros projets on se rend vite compte qu'elles sont indispensables! Mais il faut tout de même faire attention à ne pas utiliser des interfaces juste pour en utiliser! C'est là tout l'art de la conception objet.



Valid XHTML 1.1!Valid CSS!

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2007 Alain Sahli. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.