Dans ce tutoriel, nous définirons les notions de classes, d'objets, d'instance et de type avant d'écrire nos premières classes.
La programmation par objet ( POO ) a été intégrée au langage PHPdans sa version 4. Mais à cette époque, le modèle objet de PHP étaitbeaucoup trop sommaire. Nous ne pouvions réellement parler deprogrammation orientée objet. Les développeurs de PHP se sont alorspenchés sur la question et ont amélioré ce modèle objet qui, depuis laversion 5, n'a plus rien à envier aux autres langages objets comme Javaou C++.
Un « objet » est une représentation d'une chose matérielle ou immatérielle du réel à laquelle on associe des propriétés et des actions.
Exemple : une voiture, une personne, un personnage, un animal, un nombre ou bien un compte bancaire peuvent être vus comme des objets.
Les « attributs » (aussi appelés « données membres ») sont les caractères propres à un objet.
Exemple : Une personne, par exemple, possèdent différents attributs qui lui sont propres comme le nom, le prénom, la couleur des yeux, le sexe, la couleur des cheveux, la taille...
Les « méthodes » sont les actions applicables à un objet.
Exemple : Un objet personne dispose des actions suivantes : manger, dormir, boire, marcher, courir...
Une classe est une entité regroupant des variables et des fonctions. Chacune de ces fonctions aura accès aux variables de cette entité. Dans le cas du personnage, nous aurons une fonction frapper(). Cette fonction devra simplement modifier la variable $degats du personnage en fonction de la variable $force. Une classe est donc un regroupement logique de variables et fonctions que tout objet issu de cette classe possédera.
Sachez qu'en réalité, on ne les appelle pas comme ça : il s'agit d'attributs (ou propriétés) et de méthodes.
Un attribut désigne une variable et une méthode désigne une fonction.
Exemple
les classes contiennent la définition des objets que l'on va créer par la suite. Prenons l'exemple le plus simple du monde : les gâteaux et leur moule. Le moule est unique. Il peut produire une quantité infinie de gâteaux. Dans ce cas-là, les gâteaux sont les objets et le moule est la classe : le moule va définir la forme du gâteau. La classe contient donc le plan de fabrication d'un objet et on peut s'en servir autant qu'on veut afin d'obtenir une infinité d'objets.
Une « classe » est un modèle de données définissant la structure commune à tous les objets qui seront créés à partir d'elle. Plus concrètement, nous pouvons percevoir une classe comme un moule grâce auquel nous allons créer autant d'objets de même type et de même structure qu'on le désire.
Par exemple, pour modéliser n'importe quelle personne, nous pourrions écrire une classe Personne dans laquelle nous définissons les attributs (couleurs des yeux, couleurs des cheveux, taille, sexe...) et méthodes (marcher, courir, manger, boire...) communs à tout être humain.
Une instance, c'est tout simplement le résultat d'une instanciation. Une instanciation, c'est le fait d'instancier une classe. Instancier une classe, c'est se servir d'une classe afin qu'elle nous crée un objet. En gros, une instance est un objet.
Une instance est une représentation particulière d'une classe.
Lorsque l'on crée un objet, on réalise ce que l'on appelle une « instance de la classe ». C'est à dire que du moule, on en extrait un nouvel objet qui dispose de ses attributs et de ses méthodes. L'objet ainsi créé aura pour type le nom de la classe.
Par exemple, les objets Hugo, Romain, Nicolas, Daniel sont des instances (objets) de la classe Personne.
Remarque : une classe n'est pas un objet. C'est un abus de langage de dire qu'une classe et un objet sont identiques.
L'un des gros avantages de la POO est que l'on peut masquer le code à l'utilisateur (l'utilisateur est ici celui qui se servira de la classe, pas celui qui chargera la page depuis son navigateur). Le concepteur de la classe a englobé dans celle-ci un code qui peut être assez complexe et il est donc inutile voire dangereux de laisser l'utilisateur manipuler ces objets sans aucune restriction. Ainsi, il est important d'interdire à l'utilisateur de modifier directement les attributs d'un objet.
Prenons l'exemple d'un avion où sont disponibles des centaines de boutons. Chacun de ces boutons constituent des actions que l'on peut effectuer sur l'avion. C'est l'interface de l'avion. Le pilote se moque de quoi est composé l'avion : son rôle est de le piloter. Pour cela, il va se servir des boutons afin de manipuler les composants de l'avion. Le pilote ne doit pas se charger de modifier manuellement ces composants : il pourrait faire de grosses bêtises.
Le principe est exactement le même pour la POO : l'utilisateur de la classe doit se contenter d'invoquer les méthodes en ignorant les attributs. Comme le pilote de l'avion, il n'a pas à les trifouiller. Pour instaurer une telle contrainte, on dit que les attributs sont privés.
Nous venons de définir le vocabulaire propre à la programmation orientée objet. Entrons à présent dans le vif du sujet, c'est à dire la déclaration et l'instanciation d'une classe. Nous allons déclarer une classe Personne qui nous permettra ensuite de créer autant d'instances (objets) de cette classe que nous le souhaitons.
Le code ci-dessous présente une manière de déclarer et de structurer correctement une classe. Nous vous conseillons vivement de suivre ces conventions d'écriture.
Déclaration d'une classe PHP 5
<?php
class NomDeMaClasse
{
// Attributs>
// Constantes
// Méthodes
}
?>
Exemple de la classe Personne
<?php class Personne { // Attributs public $nom; public $prenom; public $dateDeNaissance; public $taille; public $sexe; // Constantes const NOMBRE_DE_BRAS = 2; const NOMBRE_DE_JAMBES = 2; const NOMBRE_DE_YEUX = 2; const NOMBRE_DE_PIEDS = 2; const NOMBRE_DE_MAINS = 2; // Méthodes public function __construct() { }
public function boire() { echo 'La personne boit<br>'; }
public function manger() { echo 'La personne mange<br>'; }
}
?>
Exemple de la classe Personnage
<?php
class Personnage
{
private $_force=20; // La force du personnage
private $_localisation; // Sa localisation
private $_experience=50; // Son expérience
private $_degats=0; // Ses dégâts
public function afficherExperience()
{
// Permet d'accéder à l'attribut private $_experience et l'afficher
echo $this->_experience;
}
public function gagnerExperience()
{
$this->_experience = $this->_experience + 1;
}
public function frapper($persoAFrapper)
{
/* L'instruction contenue dans la méthode signifie donc : « Ajoute la valeur de la force du personnage qui frappe à l'attribut $_degats du personnage frappé.*/
$persoAFrapper->_degats += $this->_force;
}
}
?>
Remarque: par convention, on écrit le nom d'une classe en « Upper Camel Case », c'est à dire que tous les mots sont accrochés et chaque première lettre de chaque mot est écrit en capital.
Comme vous pouvez le constater, nous avons déclaré 5 attributs publics, 5 constantes, 1 méthode constructeur et 2 méthodes classiques. Détaillons chaque élément.
Comme nous l'avons expliqué au début de ce cours, les attributs sont les caractéristiques propres d'un objet. Toute personne possède un nom, un prenom, une date de naissance, une taille, un sexe... Tous ces éléments caractérisent un être humain.
Par cet exemple, nous déclarons les attributs de notre classe public.
Le mot-clé public permet de rendre l'attribut accessible depuis l'extérieur de la classe. Ce n'est pas une bonne pratique à adopter mais pour ce premier exemple à gauche, nous l'utiliserons comme.
En programmation orientée objet, un attribut n'est ni plus ni moins qu'une variable.
Notez également que nous avons juste déclaré les attributs. En revanche, aucun type ni aucune valeur ne leur ont été attribués. Ils sont donc par défaut initialisés à la valeur NULL.
Remarque : deux classes différentes peuvent avoir les mêmes attributs sans risque de conflit.
Il est aussi possible de déclarer des constantes propres à la classe. Contrairement au mode procédural de programmation, une constante est déclarée avec le mot-clé const.
Remarque : une constante doit être déclarée et initialisée avec sa valeur en même temps.>
Le constructeur est une méthode particulière. C'est elle qui est appelée implicitement à la création de l'objet (instanciation).
Dans notre exemple, le constructeur n'a ni paramètre ni instruction. Le programmeur est libre de définir des paramètres obligatoires à passer au constructeur ainsi qu'un groupe d'instructions à exécuter à l'instanciation de la classe. Nous nous en passerons pour simplifier notre exemple.
Nous le détaillerons dans l'article suivant.
Remarque : en PHP, la surcharge de constructeur et de méthodes n'est pas possible. On ne peut définir qu'une seule et unique fois la même méthode.
Les méthodes sont les actions que l'on peut appliquer à un objet. Il s'agit en fait de fonctions qui peuvent prendre ou non des paramètres et retourner ou non des valeurs / objets. S'agissant d'actions, nous vous conseillons de les nommer avec un verbe à l'infinitif.
Elles se déclarent de la même manière que des fonctions traditionnelles
Au même titre que les attributs, on déclare une méthode avec un niveau de visibilité. Le mot-clé public
indique que l'on pourra appliquer la méthode en dehors de la classe, c'est à dire sur l'objet lui même.
Remarque : deux classes différentes peuvent avoir les mêmes méthodes sans risque de conflit.
Reprenons l'exemple de la méthode frapper(). Celle-ci accepte un argument : un personnage à frapper. Cependant, qu'est-ce qui vous garantit qu'on passe effectivement un personnage à frapper ?
On pourrait très bien passer un argument complètement différent, comme un nombre par exemple.
Et là, qu'est-ce qui se passe ? Une erreur est générée car, à l'intérieur de la méthode frapper(), nous essayons d'appeler une méthode sur le paramètre qui n'est pas un objet.
Il faut donc s'assurer que le paramètre passé est bien un personnage, sinon PHP arrête tout et n'exécute pas la méthode.
Pour cela, il suffit d'ajouter un seul mot : le nom de la classe dont le paramètre doit être un objet. Dans notre cas, si le paramètre doit être un objet de type Personnage, alors il faudra ajouter le mot-clé Personnage, juste avant le nom du paramètre, comme ceci :
<?php
class Personnage
{
// …
public function frapper(Personnage $persoAFrapper)
{
// …
}
}
?>
Grâce à ça, vous êtes sûrs que la méthode frapper() ne sera exécutée que si le paramètre passé est de type Personnage, sinon PHP interrompt tout le script. Vous pouvez donc appeler les méthodes de l'objet sans crainte qu'un autre type de variable soit passé en paramètre.
Le type de la variable à spécifier doit obligatoirement être un nom de classe ou alors un tableau. Si vous voulez exiger un tableau, faites précéder le nom du paramètre devant être un tableau par le mot-clé array comme ceci : public function frapper(array $coups). Vous ne pouvez pas exiger autre chose : par exemple, il est impossible d'exiger un nombre entier ou une chaîne de caractères de cette façon.des classes et des objets
Notre classe est désormais prête mais ne sert à rien tout seule. Comme nous l'avons expliqué plus haut, une classe est perçue comme un moule capable de réaliser autant d'objets de même type et de même structure qu'on le souhaite. Nous allons donc présenter maintenant la phase de concrètisation d'une classe.
L'instanciation d'une classe est la phase de création des objets issus de cette classe.
Lorsque l'on instancie une classe, on utilise le mot-clé new suivant du nom de la classe.
Cette instruction appelle la méthode constructeur ( __construct() ) qui construit l'objet et le place en mémoire.
Voici un exemple qui illustre 4 instances différentes de la classes Personne.
Création d'objets de type Personne
<?php
$personne1 = new Personne();
$personne2 = new Personne();
$personne3 = new Personne();
$personne4 = new Personne();
Un objet est en fait une variable dont le type est celui de la classe qui est instanciée.
Remarque : si nous avions défini des paramètres dans la méthode constructeur de notre classe, nous aurions du les indiquer entre les parenthèses au moment de l'instance. Par exemple : $personne1 = new Personne('Hamon','Hugo');
Nous venons de créer 4 objets de même type et de même structure. Dans l'état actuel, ce sont des clones car leurs attributs respectifs sont tous déclarés mais ne sont pas initialisés. Nous affectons à présent des valeurs à chacun des attributs de chaque objet.
Utilisation des attributs d'un objet
<?php // Définition des attributs de la personne 1 $personne1->nom = 'Hamon'; $personne1->prenom = 'Hugo'; $personne1->dateDeNaissance = '02-07-1987'; $personne1->taille = '180'; $personne1->sexe = 'M'; // Définition des attributs de la personne 2 $personne2->nom = 'Dubois'; $personne2->prenom = 'Michelle'; $personne2->dateDeNaissance = '18-11-1968'; $personne2->taille = '166'; $personne2->sexe = 'F'; // Définition des attributs de la personne 3 $personne3->nom = 'Durand'; $personne3->prenom = 'Béatrice'; $personne3->dateDeNaissance = '02-08-1975'; $personne3->taille = '160'; $personne3->sexe = 'F'; // Définition des attributs de la personne 4 $personne4->nom = 'Martin'; $personne4->prenom = 'Pierre'; $personne4->dateDeNaissance = '23-05-1993'; $personne4->taille = '155'; $personne4->sexe = 'M';
Nous avons maintenant des objets ayant chacun des caractèristiques différentes.
Dans notre exemple, nous accèdons directement à la valeur de l'attribut. Cela est possible car nous avons défini l'attribut comme étant public. Si nous avions déclaré l'attribut avec les mots-clés private ou protected, nous aurions du utiliser un autre mécanisme pour accéder à sa valeur ou bien la mettre à jour. Nous verrons cela dans un prochain cours.
La lecture de la valeur d'un attribut d'un objet se fait exactement de la même manière que pour une variable traditionnelle.
Le code suivant présente comment afficher le nom et le prénom de la personne 1.
$personne1->nom
$personne1 : L'objet crée au-dessus
-> : opérateur
nom : L'attribut $nom crée au-dessus (Vous remarquerez que l'on ne remet pas le $)
<?php
echo 'Personne 1 :<br><br>';
echo 'Nom : ', $personne1->nom ,'<br>';
echo 'Prénom : ', $personne1->prenom;
?>
L'exécution de ce programme produit le résultat suivant sur la sortie standard :
L'accès aux constantes ne peut se faire qu'en lecture via l'opérateur ::
Classe::CONSTANTE
L'exemple suivant illustre la lecture d'une constante de la classe Personne.
<?php
echo 'Chaque personne a ', Personne::NOMBRE_DE_YEUX ,' yeux.';
?>
Remarque : si l'on tente de redéfinir la valeur d'une constante, PHP génèrera une erreur de ce type :
Leur utilisation est exactement la même que pour les attributs.
Rappellez-vous, nous avions défini deux méthodes pour notre classe Personne. Il s'agit des méthodes boire() et manger(). Toutes deux affichent une chaine de caractères sur la sortie standard lorsqu'elles sont exécutées.
Reprenons nos 4 objets précédents. Nous simulons que ces 4 personnes sont à table et qu'elles dînent. Simultanément les deux premières personnes boivent le contenu d'un verre pendant que les deux autres mangent. Cela se représente donc par l'appel de la méthode boire() sur les objets personne1 et personne2, puis par l'appel de la méthode manger() sur les objets personne3 et personne4.
Appel de méthode sur des objets
<?php $personne1->boire(); $personne2->boire(); $personne3->manger(); $personne4->manger(); ?>
Après exécution, le résultat est le suivant :
Remarque : comme pour le constructeur, si nos méthodes avaient eu besoin de paramètres en entrée, nous les aurions indiqués au moment de l'appel entre les parenthèses de la fonction.