|
Classes et objets en PHP
|
| Auteur |
Message |
CrazyCat
Administrator
      
Messages : 130
Groupe : Administrateurs
Inscription : Feb 2007
Statut :
Absent
Réputation : 0
|
De plus en plus, on entend parler de POO (Programmation Orientée Objet).
Les habitués de java (entre autres) connaissent ça par coeur, mais c'est un concept qui n'a atteint sa maturité en PHP que depuis l'avènement de PHP5.
Tout d'abord, qu'est-ce qu'un objet?
C'est tout simplement un élément qui se définit par des propriétés et des méthodes et qui est utilisable à plusieurs moments.
Prenons l'exemple d'une porte, qui est un objet courant. On peut lui définir des propriétés qui seront son état (ouverte, fermée, verouillée) et la pièce (ce qui la rend unique). On peut aussi lui définir des méthodes qui seront ouvrir, fermer, verrouiller, déverouiller.
Vous voyez donc comment l'objet porte peut être appelé plusieurs fois au même moment: si vous définissez votre maison, vous aurez porte(entrée), porte(cuisine), ...
Un objet contient 2 méthodes par défaut (en PHP5), c'est ce qu'on appelle le constructeur et le destructeur.
Le constructeur permet d'initialiser l'objet, donc de lui donner ses paramêtres initiaux. En PHP4, le constructeur se fait en créant dans l'objet une fonction dont le nom est celui de l'objet, alors qu'en PHP5 il y a une fonction __construct()
Le destructeur sert à supprimer cet objet, il n'existe réellement qu'en PHP5.
Pour l'instant, nous nous limiterons à l'utilisation en PHP4.
Comment définir notre porte?
Nous allons créer une classe (qui est donc la définition de l'objet) en lui donnant des paramètres par défaut.
class porte {
// par defaut, une porte est fermee, nous initialisons donc son etat par défaut
var $etat = "fermee";
function porte($nom,$etat='') {
// le constructeur: une porte est obligatoirement definie par son nom
// l'etat initial de la porte peut etre defini
$this->nom = $nom;
if ($etat != '') {
$this->etat = $etat;
}
}
}
nous avons donc créé un objet porte qui n'a pas de méthode et qui a 2 propriétés: son nom et son état initial.
Nous allons rajouter les 4 méthodes en tenant compte de certains impératifs:
- une porte ne peut être ouverte que si elle est déverouillée mais fermée,
- une porte ne peut être fermée que si elle est ouverte,
- une porte ne peut être verouillée que si elle est fermée,
- une porte ne peut être déverouillée que si elle est verouillée.
class porte {
var $etat = "fermee";
function porte($nom,$etat='') {
$this->nom = $nom;
if ($etat != '') {
$this->etat = $etat;
}
}
function ouvrir() {
if ($this->etat == "fermee") {
$this->etat = "ouverte";
}
}
function fermer() {
if ($this->etat == "ouverte") {
$this->etat = "fermee";
}
}
function verouille() {
if ($this->etat == "fermee") {
$this->etat = "verouillee";
}
}
function deverouille() {
if ($this->etat == "verouillee") {
$this->etat = "deverouillee";
}
}
}
nous avons donc nos 4 méthodes et chacune tient compte de l'état précédent de la porte.
nous pouvons tester notre objet...
// on declare la nouvelle porte, dans son etat par defaut
$entree = new porte("entree_principale");
// on verifie l'etat
echo $entree->etat."<br />";
// on ouvre la porte
$entree->ouvre();
// on verifie l'etat
echo $entree->etat."<br />";
// on essaye de verouiller la porte ouverte
$entree->verouille();
// on verifie l'etat
echo $entree->etat;
Nous devrions avoir comme affichage:
fermee
ouverte
ouverte
Ainsi, vous venez de voir comment on crée un modèle d'objet, comment on appelle de manière simple une méthode et comment on peut utiliser les propriétés.
La prochaine étape fera intervenir deux points très importants:
- passer des paramètres à une méthode,
- hériter un objet.
L'erreur est humaine, mais il faut un ordinateur pour provoquer une catastrophe
Ce message a été modifié le: 15/02/2007 11:00 par CrazyCat.
|
|
| 29/12/2006 15:02 |
|
 |
Learner
Junior Member
 
Messages : 12
Groupe : Membres
Inscription : Nov 2006
Statut :
Hors ligne
Réputation : 0
|
Salut,
impec merci !
Ca fait 3 semaines que je fait php et je n'ai pas toucher cette notion de POO.Mais grace a ce tutoriel,j'ai fait une bonne idee,j'attend la 2 eme partie!
|
|
| 30/12/2006 23:42 |
|
 |
CrazyCat
Administrator
      
Messages : 130
Groupe : Administrateurs
Inscription : Feb 2007
Statut :
Absent
Réputation : 0
|
RE: Classes et objets en PHP
Et bien voici la deuxième partie...
Tout d'abord, résumons vite la partie précédente:
- Un objet se crée en faisant une classe
- Les méthodes sont des fonctions de cette classe
- Les propriétés sont des variables de cette classe
Vous aurez remarqué que l'on fait les appels internes avec le mot-clé "this" qui représente la classe (l'objet) courant.
Attaquons nous maintenant à l'héritage. Cette notion permet en fait d'étendre l'objet pour lui ajouter des propriétés et des méthodes. Par exemple, nous allons partir de notre porte "basique" et l'adapter à notre maison.
class porte_modifiee extends porte {
var $couleur = "bois";
function porte_modifie($nom, $etat='', $couleur='') {
$this->nom = $nom;
if ($etat != '') {
$this->etat = $etat;
}
if ($couleur != '') $this->couleur = $couleur;
}
}
le premier point important est le mot-clé extends qui permet de définir l'héritage: porte_modifiee etend l'objet porte, cela veut donc dire que toutes les propriétés de l'objet porte font partie de l'objet porte_modifiee.
le second point important concerne le constructeur: nous n'appelons pas le constructeur de l'objet initial, il faut donc que le constructeur de l'objet étendu gère les paramètres par défaut.
Maintenant, nous allons créer une fonction pour repeindre la porte, donc pour modifier la couleur. elle est très simple:
class porte_modifiee extends porte {
var $couleur = "bois";
function porte_modifie($nom, $etat='', $couleur='') {
$this->nom = $nom;
if ($etat != '') {
$this->etat = $etat;
}
if ($couleur != '') $this->couleur = $couleur;
}
function repeindre($couleur) {
if ($this->etat == 'ouverte') {
$this->couleur = $couleur;
} else {
return "vous ne pouvez pas peindre une porte fermee";
}
}
}
vous constatez que depuis l'objet étendu, on peut atteindre une propriété de l'objet initial sans le moindre soucis, ce qui est logique.
attention: la déclaration des valeurs initiales telle que je l'ai faite dans les exemples n'est pas réellement juste, même si elle fonctionne.
Il vaut mieux simplement initialiser le type de variables et utiliser le constructeur pour affecter les valeurs par défaut.
Voici ce que donne notre code final et propre:
<?
class porte {
var $etat;
function porte($nom,$etat='') {
$this->nom = $nom;
if ($etat != '') {
$this->etat = $etat;
} else {
$this->etat = 'fermee';
}
}
function ouvrir() {
if ($this->etat == "fermee") {
$this->etat = "ouverte";
}
}
function fermer() {
if ($this->etat == "ouverte") {
$this->etat = "fermee";
}
}
function verouille() {
if ($this->etat == "fermee") {
$this->etat = "verouillee";
}
}
function deverouille() {
if ($this->etat == "verouillee") {
$this->etat = "deverouillee";
}
}
}
class porte_modifiee extends porte {
var $couleur;
function porte_modifiee($nom, $etat='', $couleur='') {
$this->nom = $nom;
if ($etat != '') {
$this->etat = $etat;
} else {
$this->etat = 'fermee';
}
if ($couleur != '') {
$this->couleur = $couleur;
} else {
$this->couleur = 'bois';
}
}
function repeindre($couleur) {
if ($this->etat == 'ouverte') {
$this->couleur = $couleur;
} else {
return "vous ne pouvez pas peindre une porte fermee";
}
}
}
$maporte = new porte_modifiee("principale", "", "bleue");
echo $maporte->nom." -- ".$maporte->etat." -- ".$maporte->couleur;
?>
L'erreur est humaine, mais il faut un ordinateur pour provoquer une catastrophe
Ce message a été modifié le: 15/02/2007 10:58 par CrazyCat.
|
|
| 02/01/2007 11:27 |
|
 |
Learner
Junior Member
 
Messages : 12
Groupe : Membres
Inscription : Nov 2006
Statut :
Hors ligne
Réputation : 0
|
Salut j'ai une une question :-[,
On regardant certains scripts je vois bcq l'operateur & quand on creer des objets,
$objet=& new classquelconque();
Je sais que ca veut dire partager le contenu mais la quel es le contenu les valeurs de constructeur ?
Merci !
|
|
| 18/01/2007 00:01 |
|
 |
CrazyCat
Administrator
      
Messages : 130
Groupe : Administrateurs
Inscription : Feb 2007
Statut :
Absent
Réputation : 0
|
Il s'agit de ce que l'on appelle le passage par référence.
A priori, lorsqu'on utilise une fonction, ou une classe, on travaille sur une copie de la variable, d'ou l'intérêt de la ligne "return $result" ou de l'affectation d'une propriété ($this->result = $result)
Le passage d'une variable par référence va signaler que l'on travaille sur la variable elle-même, l'exemple le plus courant étant:
<?
function increm(&$int) {
$int++;
}
$a = 2;
echo "a = $a<br />n"; // affiche "a = 2"
increm($a);
echo "a = $a<br />n"; // affiche "a = 3";
?>
Ceux qui connaissent le vb (par exemple) auront reconnu la différence entre function et sub
Dans l'exemple que tu donnes, on demande en fait à la fonction de retourner une référence, le constructeur est alors:
function &classquelconque() {
...
}
De toutes manières, je te conseille d'éviter de te servir de cela car cela provoque des warning en php 4.3+ et des erreurs fatales en php5, ces versions gérant elles-même les références.
L'erreur est humaine, mais il faut un ordinateur pour provoquer une catastrophe
|
|
| 18/01/2007 09:23 |
|
 |
coca25
Junior Member
 
Messages : 20
Groupe : Membres
Inscription : Nov 2006
Statut :
Hors ligne
Réputation : 0
|
bonjour tout le monde,
la question sur les références est intéressante (je les ai jamais utilisé pour un constructeur)
mais à la lecture du post, je me pose une question:
new crée une instance de la classe, donc en théorie, l'objet n'existe pas avant le new
par conséquence quel est la différence entre :
$instance = &new UneClasse();
et
$instance = new UneClasse();
la seule raison que je vois est que le constructeur détruit l'instance de la classe et renvoie une référence vers une instance déjà existance ou recréée
ou alors j'ai tout faux
|
|
| 18/01/2007 10:18 |
|
 |
CrazyCat
Administrator
      
Messages : 130
Groupe : Administrateurs
Inscription : Feb 2007
Statut :
Absent
Réputation : 0
|
En fait, l'appel d'une classe par référence est une astuce utilisée avant le php 4.3 qui n'a qu'un but, faker un destructeur.
Lorsque tu appelles ta classe par référence, tu peux ensuite faire unset($instance).
Tu as donc détruit l'instance complètement, et non pas une "copie".
L'erreur est humaine, mais il faut un ordinateur pour provoquer une catastrophe
|
|
| 18/01/2007 11:18 |
|
 |
Learner
Junior Member
 
Messages : 12
Groupe : Membres
Inscription : Nov 2006
Statut :
Hors ligne
Réputation : 0
|
Merci crazycat pour les explications donné,
En fait, l'appel d'une classe par référence est une astuce utilisée avant le php 4.3 qui n'a qu'un but, faker un destructeur.
Lorsque tu appelles ta classe par référence, tu peux ensuite faire unset($instance).
Tu as donc détruit l'instance complètement, et non pas une "copie".
Sinon je vois pas vraiment pourquoi utilisé les références avec new,et c'est le cas de script Vbulletin dont tous les appels des class sont par references ???
|
|
| 18/01/2007 23:48 |
|
 |
Yayef
Junior Member
 
Messages : 17
Groupe : Membres
Inscription : Dec 2006
Statut :
Hors ligne
Réputation : 0
|
Je voudrais juste signaler en toute généralité que le passage par référence ou par valeur n'a pas que des conséquences au niveau de la programmation. Ca a aussi des conséquences sur les performances : un passage par valeur nécessitant une copie... de la valeur, c'est plus gourmand en ressources qu'un passage par référence. Ce qui explique par exemple que pour les langages de programmation qui privilégient le passage par valeur en général, certains gros objets soient quand même d'office passés par référence (c'est souvent le cas des tableaux).
Moitié kangourou, moitié perroquet, c'est une souris.
Si les gens qui disent du mal de moi savaient exactement ce que je pense d'eux, ils en diraient bien davantage. (Sacha Guitry)
|
|
| 19/01/2007 08:56 |
|
 |
CrazyCat
Administrator
      
Messages : 130
Groupe : Administrateurs
Inscription : Feb 2007
Statut :
Absent
Réputation : 0
|
Et c'est pour cela que le système de gestion des classes de PHP5 gère lui-même l'utilisation ou non du passage par références.
Concernant vbulletin et les gros systèmes multi-utilisateurs, je pense que l'utilisation des références est pour deux raisons:
1) comme l'a dit Yayef, limiter l'utilisation de la mémoire
2) éviter certains effets de bords (une variable modifiée par un autre utilisateur, ça c'est déjà vu)
L'erreur est humaine, mais il faut un ordinateur pour provoquer une catastrophe
|
|
| 19/01/2007 09:46 |
|
 |
|
|