Au mois de septembre de l’année 2010, je vous présentais un article concernant la programmation orientée objet (POO) dans lequel je devais vous fournir trois articles pour avancer dans la compréhension de ce terme. Malheureusement j’ai oublié de réaliser ceux-ci, mais ils sont toujours d’actualités alors allons-y !
En tant que développeur PHP, vous le savez vous pouvez créer des systèmes fonctionnels sans utiliser des classes et des objets, vous évitant ainsi de créer une classe unique. Même si vous décidez de ne pas intégrer la programmation orientée objet dans votre propre code, vous aurez probablement besoin de connaître la POO. Par exemple, si vous utilisez une bibliothèque tierce, telles que celles mises à disposition par PHP Extension and Application Repository (PEAR), vous vous trouverez dans l’obligation d’instancier des objets pour appeler des méthodes.
Qu’est-ce qu’une classe ? Qu’est-ce qu’un objet ?
En d’autres termes, une classe est un bloc où est défini un ensemble de propriétés et de méthodes. Généralement ces composants sont unis autour d’une unique responsabilité ou un ensemble de responsabilités. Dans cet article, vous allez créer une classe exposant des méthodes d’interrogation et d’insertion d’un gestionnaire de contacts.
Une classe peut être utilisée directement vous permettant d’utiliser simplement un tas de méthodes (fonctions) et de propriétés (variables). C’est ignorer une dimension puissante, cependant les classes peuvent être utilisées pour générer plusieurs instances en mémoire. Ces cas sont appelés objets. Chaque objet a accès au même ensemble de fonctions (appelées méthodes dans un contexte orienté objet), et variables (appelées propriétés ou variables d’instance), mais la valeur réelle de chaque variable peut différer d’un objet à un autre.
L’exemple qui est généralement repris dans tous les livres de POO, c’est la comparaison avec un jeu de rôle, et plus particulièrement un jeu de rôle comprenant un tank. Imaginez une classe définissant un ensemble de variables pour ce dernier : capacités défensives et offensives, rang, santé, et ainsi de suite. La classe peut également définir un ensemble de fonctions, tels que : move()
et attack()
. Bien que le système contienne une classe tank, cette classe peut être utilisée pour générer des dizaines ou des centaines d’objets tanks, ayant chacun éventuellement ses propres caractéristiques (santé, rang, …). Une classe est donc un plan ou un modèle à utiliser pour générer des objets.
Cet exemple est peut-être la meilleure façon de comprendre les classes et les objets à créer.
Classe = Propriétés + Méthodes
Tank = Caractéristiques + Capacités
Objet = Identité (unicité, référence) + État (propriétés) + Comportement (méthodes)
Un objet est donc une représentation d’une chose matérielle ou immatérielle du réel à laquelle on associe une identité, des propriétés (un état) et des actions (un comportement). Autrement dit, Il peut être défini comme une entité possédant un état interne, sur lequel il est possible d’exercer des actions et exposant des propriétés externes.
Note : Dans la suite de cet article, le nom des classes, fonctions, variables, … seront définis en anglais.
Votre première classe
Pour créer une classe, vous allez utiliser le mot-clé class
. À sa plus simple expression, une classe se compose du mot-clé class
, un nom, et un bloc de code:
class CarnetAdresse {}
[/sourcecode]
Le nom de la classe peut contenir n’importe quelle combinaison de lettres et de chiffres, ainsi que le caractère de soulignement (_), mais ne peut pas commencer par un chiffre.
La classe CarnetAdresse
dans l’exemple précédent est parfaitement légale, même si elle est d’une utilité limitée.
Alors, comment utilisez-vous cette classe pour créer des objets ?
$obj1 = new CarnetAdresse();
$obj2 = new CarnetAdresse();
… = new CarnetAdresse();
[/sourcecode]
La forme en moins, l’instanciation d’un objet est semblable à un appel de fonction. Comme lors d’un appel de fonction, vous devez fournir les parenthèses. Comme les fonctions, certaines classes exigent que vous passiez des arguments. Vous devez également utiliser le nouveau mot-clé new
: cela signifie que vous souhaitez instancier un nouvel objet. L’objet retourné peut alors être stocké dans une variable pour une utilisation ultérieure.
Propriétés
Dans le corps d’une classe, vous pouvez déclarer des variables spéciales appelées propriétés. En PHP V4, les propriétés doivent être déclarées avec le mot-clé var
. Cette syntaxe est toujours d’actualité en PHP 5, mais surtout pour des raisons de compatibilité ascendante.
En PHP 5, les propriétés peuvent être déclarées publiques, privées ou protégées (public
, private
et protected
). Le listing ci-dessous présente une classe qui déclare deux propriétés. Pour l’instant, on va déclarer toutes les propriétés publiques dans les exemples.
class CarnetAdresse {
public $persons = array();
public $type = "buisiness";
}
[/sourcecode]
Comme vous pouvez le voir, vous pouvez déclarer une propriété et attribuer sa valeur en même temps. Vous pouvez obtenir un rapide coup d’œil à l’état d’un objet avec la fonction print_r()
. Le nouveau listing ci-dessous montre qu’un objet CarnetAdresse
possède désormais de nouvelles propriétés.
$buis = new CarnetAdresse();
print_r($buis);
// Si vous exécutez ce script, vous verrez à l’écran ceci :
CarnetAdresse Object ( [persons] => Array ( ) [type] => buisiness )
[/sourcecode]
Vous pouvez accéder aux propriétés de l’objet en utilisant l’opérateur ->
. Donc $pro->type
désigne la propriété de $type
de l’objet CarnetAdresse
référencé par $buis
.
Si vous pouvez accéder à une propriété, cela signifie que vous pouvez définir et obtenir sa valeur. Le code du listing ci-dessous crée deux instances de la classe CarnetAdresse
– en d’autres termes, il instancie deux objets CarnetAdresse
. On change la propriété $type
d’un objet et ajoute à la fois les personnes :
$buis = new CarnetAdresse();
$buis->persons[] = "OpenXtrem";
$perso = new CarnetAdresse();
$perso->type = "personal";
$perso->persons[] = "Yohann P.";
$array = array($buis, $perso);
foreach ($array as $_contact) {
echo "Type : – {$_contact->type} – ";
echo "Premier contact : {$_contact->persons[0]} <br />";
}
[/sourcecode]
Le script affiche le texte suivant :
Ainsi, la classe CarnetAdresse
est maintenant un peu plus utile. Les objets individuels peuvent stocker des ensembles distincts de clés et de valeurs. Ici, même si la classe CarnetAdresse
est actuellement un peu plus qu’un tableau associatif, une idée se trame derrière sur la puissance des objets. A ce stade, nous pourrions très bien représenter les données présentées dans le listing ci-dessus, comme ceci :
$buis = array(
‘persons’=>array( ‘Openxtrem’ ),
‘type’=>’buisiness’
);
$perso = array(
‘persons’=>array( ‘Yohann P’ ),
‘type’=>’personal’
);
[/sourcecode]
Bien que cette structure de données remplisse le même but que la classe CarnetAdresse
, il ne fournit aucune garantie sur la structure. Si vous êtes passé par un objet CarnetAdresse
, vous le savez, il est conçu pour avoir une propriété persons
, ce que vous n’avez pas avec un tableau associatif. Pour ce dernier, il est nécessaire de faire une requête à l’aveuglette pour obtenir la valeur souhaitée : $buis["pressons"][0]
, à moins que le code faisant la requête est sûr de la provenance des informations du tableau.
C’est un point clé sur les objets : le type d’un objet est une garantie de ses caractéristiques. Les objets peuvent être des choses, mais fondamentalement ils peuvent aussi faire des choses.
Méthodes
En d’autres termes, les méthodes sont des fonctions déclarées dans une classe. Elles sont généralement – mais pas toujours – appelées par une instance d’objet. Le listing ci-dessous ajoute une méthode à la classe CarnetAdresse
et un objet l’appelle.
class CarnetAdresse {
public $persons = array();
public $type ="buisiness";
function resume() {
$ret = "Type du carnet d’adresses : {$this->type} <br />";
$ret .= "CarnetAdresse: ".count($this->persons)."<br />";
return $ret;
}
}
$buis = new CarnetAdresse();
$buis->persons[] = "Openxtrem";
echo $buis->resume();
[/sourcecode]
La sortie nous donne :
Comme vous pouvez le constater, la méthode resume
est déclarée comme une fonction serait déclarée, sauf qu’elle se fait dans une classe. Dans notre exemple, la méthode est appelée en utilisant notre objet. La fonction accède aux propriétés pour fournir un bref aperçu de l’état de l’objet.
Notez l’utilisation d’une nouvelle fonctionnalité à cet article. La pseudo-variable $this
fournit un mécanisme pour qu’un objet puisse se référer à leurs propres propriétés et méthodes. En dehors de la classe, vous devez manipuler l’objet pour accéder à ses éléments ($buis
, dans notre cas). A l’intérieur d’une classe, vous devez donc vous rabattre sur le $this
.
Les classes sont souvent représentées dans des diagrammes à l’aide du langage Universal Modeling Language (UML). Les détails de l’UML sont au-delà du champ d’application de cet article, mais de tels diagrammes sont néanmoins un excellent moyen de visualiser le détail d’une classe. L’image ci-dessous nous montre la classe CarnetAdresse
telle qu’elle est. Le nom de classe se trouve en haut, les propriétés au milieu et les méthodes à la base.
Constructeur
Le moteur PHP reconnaît un certain nombre de méthodes « magiques ». Si elles sont définies, il appelle ces méthodes automatiquement lorsque les circonstances correctes surgissent. La méthode la plus généralement mise en œuvre est celle du constructeur. Le moteur PHP appelle un constructeur lorsque l’objet est instancié. Il est l’endroit idéal pour mettre le code initial essentiel pour votre objet. En PHP V4, vous créez un constructeur en déclarant une méthode avec le même nom que celui de la classe. Dans la version 5, vous devez déclarer une méthode appelée __construct()
. Le prochain listing montre un constructeur qui nécessite deux paramètres.
class CarnetAdresse {
public $persons = array();
public $type;
public $contact;
function __construct( $type, Contact $contact) {
$this->type = $type;
$this->contact =$contact;
}
//…
[/sourcecode]
Pour instancier un objet CarnetAdresse
, vous devez passer un type string
et d’un objet Contact
à son constructeur. Ce dernier utilise ces paramètres pour définir ses propres propriétés. Voici comment vous pourriez maintenant instancier un objet CarnetAdresse
:
$buis = new CarnetAdresse( "buisiness", new Contact());
[/sourcecode]
Le classe CarnetAdresse
est maintenant beaucoup plus sûre qu’avant. Vous savez que tout objet CarnetAdresse
aura été initialisé avec les arguments requis.
Remarque : la programmation par objet n’est pas synonyme de bonne programmation. Il existe d’excellents développeurs capables de produire du bon code procédural, maintenable, structuré et modulaire. Mais il existe aussi des développeurs en programmation objet qui produisent du mauvais code suite à un manque de conceptualisation.
Conclusion
Voici ce que vous devez retenir à la fin de cette première partie :
Les classes permettent :
- d’implémenter des structures de programmes orientées objet
- de créer des éléments possédant des structures complexes et leurs propres fonctions
- les valeurs décrivant cet objet sont appelées variables membres
- les fonctions internes à ces objets sont appelées fonctions membres
- elles implémentent le paradigme objet
S’il est important de comprendre l’éventail des outils disponibles en PHP pour la programmation orientée objet, il est également crucial d’envisager la meilleure façon de travailler avec de telles caractéristiques.
C’est ainsi que va se conclure la première des trois parties sur la Programmation Orientée Objet en PHP. La prochaine, vous sera présentée la semaine prochaine dans laquelle seront abordées les notions du mot clé statique, de l’encapsulation et l’héritage. Enfin, la dernière partie sera une mise en application pour comprendre quand et comment vous pouvez réellement utiliser ces techniques en interrogeant une base de données MySQL et un service Web.
Cet article vous a t-il permis de mieux aborder la notion de la Programmation Orientée Objet ?