Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
Des questions suite à mon introduction ?
Eh mais attends bonhomme, pourquoi diable intancierais-je une classe qui ne sera tout bonnement utilisée qu'une fois ?
T'as tout compris, "bonhomme" (

) ! Dites-vous bien que créer un objet utilise des ressources, et donc ralentit votre script (plus ou moins visiblement, évidemment) ! A quoi cela sert-il de pouvoir créer deux instances de notre gestionnaire d'erreurs ou de notre template ? Au cours d'une même requête, ces classes ne doivent rationnellement exister qu'en un exemplaire.
Prenons un exemple simple que nous pouvons vivre sur nos PC.
Bien qu'impossible au départ, un plug-in de MSN Messenger permet d'ouvrir deux comptes en même temps, ici, pouvoir ouvrir deux instances de MSN est totalement justifié. Alors qu'au contraire, avoir deux instances de Steam lancées est inutile puisque de toute manière, vous ne pourrez jouer qu'à un jeu à la fois.
Et si j'ai envie d'avoir accès à tout moment à des jeux situés sur deux comptes Steam différents ?

Alors là, tu es en train de bousiller mon exemple (

), et de toute façon les gens ont bien compris ce que j'entendais par là...
Cependant, ne vous méprenez pas : je ne suggère pas ici que l'instanciation des classes est inutile, cela reviendrait à dire que les objets sont inutiles. Je dis seulement que les utiliser - disons "basiquement" - n'est pas toujours la meilleure façon de procéder, la plus optimisée. Heureusement, les génies au quotient intellectuel supérieur y ont pensé avant moi, et ils ont prévu le coup !
Abstraction
Ce à quoi ces messieurs ont pensé porte le doux(loureux) nom d'
abstraction de classes.
Avant que l'autre #*$£!°^ ne se réveille avec ses questions, je vais anticiper et vous expliquer la chose.
Tout d'abord, il faut savoir que la notion d'abstraction vient avec ses amies les méthodes et propriétés statiques. Finissez vos tubes d'aspirine et écoutez, nous allons déjà laisser la documentation PHP définir ce qu'est une classe abstraite.
Citation : Documentation PHPPHP 5 introduit les classes (...) abstraites. Il n'est pas autorisé de créer une instance d'une classe définie comme abstraite.
Donc jusque-là, pas d'embrouille : si on déclare une classe comme étant abstraite, on ne pourra pas l'instancier. Voilà ! Notre problème est réglé, je vous souhaite une bonne continuation...

Nan, ça serait trop infâme de ma part de vous laisser dans le bourbier (surtout qu'une foule en colère, ça fait mal), on va aller un peu plus loin.
Comment diantre crée-t-on une classe abstraite, me demanderez-vous.

Ainsi, vous répondrai-je !
Code : PHP 1
2
3
4
5
6
7
8
9
10
11 | <?php
abstract class myabstractclass
{
public $foo;
public function display($str)
{
echo $str;
}
}
?>
|
En ce qui concerne la définition d'une classe abstraite, seule la première ligne nous intéresse, cela consiste simplement à ajouter le mot-clé
abstract devant le mot-clé
class. Comme je l'ai dit tout à l'heure, pas d'embrouille !

Essayons d'instancier cette classe...
Code : PHP1
2
3 | <?php
$bar = new myabstractclass;
?>
|
Et comme attendu, nous voilà gratifiés d'un agréable message d'erreur.
Code : Console | Fatal error: Cannot instantiate abstract class myabstractclass in /srv/www/dev/tuto-abstract/abstract.php on line 12 |
Accès aux membres depuis l'extérieur
Euh, ouais, bah t'es bien beau toi, mais comment j'vais faire pour accéder à ma propriété et à ma méthode, si aucune variable ne contient un objet ?
Ah, il s'est réveillé ! Ce n'est cependant pas une mauvaise question : d'habitude, quand on instancie une classe, ma variable
$bar (voir ci-dessus) aurait contenu mon objet, et j'aurais donc pu accéder à ses membres. Mais ici non, alors comment faire ? Le nom de la classe étant la seule trace que nous ayons de cette structure, nous allons donc l'utiliser. Mais pas comme d'habitude : nous allons utiliser un nouvel opérateur pour remplacer
"->" (préparez les tubes) :
Paamayim Nekudotayim !
Et je le trouve où, ce type ?
Sache pour ta gouverne, que
Paamayim Nekudotayim signifie "double deux points" en hébreu. Vous vous imaginez donc que ce nouvel opérateur si génial va être
"::". Il est appelé
opérateur de résolution de portée car basiquement, il permet d'accéder "directement" à n'importe quelle classe qui a été définie, qu'elle ait été instanciée ou non.
Une chose importante à noter avant de faire l'erreur est que contrairement à la "notation objet", il
FAUT mettre le symbole du dollar ("
$") devant les noms d'attributs.
Code : PHP1
2
3
4 | <?php
$foo?>attribute = 'Bar';
foo::$attribute = 'Bar';
?>
|
Constructeurs, destructeurs
Une autre chose importante qui devrait couler de source dans vos esprits, c'est le fait que puisque la classe n'est pas instanciée, aucune méthode constructeur (ou destructeur) n'est appelée ; pour en simuler une, vous devez l'appeler explicitement. Généralement, dans mon architecture, j'ai une méthode
init() dans chaque classe qui joue le rôle d'un constructeur.
Mettons en oeuvre les deux dernières notions que nous avons apprises.
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | <?php
abstract class myabstractclass
{
public $foo;
public function init()
{
self::$foo = 'Hello World! (Parce que j\'en ai marre des foo et des bar)';
}
public function display($str)
{
echo $str;
}
}
myabstractclass::init();
echo myabstractclass::$foo;
?>
|
Voici ce qui s'affiche !
dit-il dans un cri de victoire.
Code : Console | Fatal error: Access to undeclared static property: myabstractclass::$foo in /srv/www/dev/tuto-abstract/abstract.php on line 8 |
Staticité (probable néologisme)
Et là je crie "Horreur" ! Que se passe-t-il ? Si vous lisez attentivement le message d'erreur, vous pouvez au moins reconnaître le mot
static dont je vous ai parlé tout à l'heure. Littéralement, l'erreur raconte que j'ai essayé d'accéder à un membre qui n'a pas été déclaré comme membre statique ! Mais qu'est-ce que la staticité (je ne sais pas si ce mot existe mais j'aime bien, alors chut !) ?
D'après notre amie la documentation PHP, nous apprenons cela :
Citation : Documentation PHPLe fait de déclarer des membres ou des méthodes comme statiques vous permet d'y accéder sans avoir besoin d'instancier la classe.
Tu nous avais caché cette information ? Vieux filou, brigand, gredin, malotru !
Disons que je vous ménageais, chaque chose en son temps. Maintenant que nous savons cela, nous pouvons simplement rajouter le mot-clé
static entre le mot-clé de visibilité (
public,
protected ou
private) et le nom de l'attribut. Le problème est maintenant réglé.
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | <?php
abstract class myabstractclass
{
public static $foo;
public static function init()
{
self::$foo = 'Hello World! (Parce que j\'en ai marre des foo et des bar)';
}
public static function display($str)
{
echo $str;
}
}
myabstractclass::init();
echo myabstractclass::$foo;
?>
|
Euh... Tu as aussi déclaré les méthodes comme étant statiques. Elles non plus ne peuvent pas être appelées sans ça ?
Pas exactement ; en réalité, pour cela il faut se dire que la staticité (encore celui-là) n'est pas forcément dépendante de l'abstraction : voyons le tableau ci-dessous pour plus d'éclaircissement (ou de confusion, au choix).
Correspondances abstraction / staticité pour les méthodes
| | Statique | Non statique |
|---|
| Classe abstraite |
Ne peut être appelée que statiquement |
Ne peut être appelée que statiquement |
| Classe non abstraite |
Ne peut être appelée que statiquement |
Peut être appelée statiquement et non statiquement |
Basiquement, l'abstraction oblige à appeler en statique, mais on peut forcer à appeler en statique même en classe non abstraite. Bon, si vos cerveaux sont encore un poil lucides après ce tableau illisible, vous devez vous dire que définir une méthode comme étant statique dans une classe abstraite est totalement inutile... Et vous auriez raison ! Je le mets simplement pour avoir une certaine homogénéité dans mon code.
- Dans une classe abstraite ne peuvent être appelés que les membres statiques ;
- dans une classe abstraite, les méthodes sont implicitement déclarées statiques ;
- dans une classe "concrète", on peut obliger à appeler un membre statiquement.
Accès aux membres intérieurement
Une dernière chose à voir, c'est l'accès aux membres d'une classe depuis cette même classe :
$this étant désuet ici puisque la classe n'est pas instanciée, il va falloir trouvée autre chose. C'est ici qu'apparait
self ! Il symbolise tout simplement la classe en cours.
Et après on utilise
Narabuth Shinoptyies (

) comme tout à l'heure ?
Oui, exactement ; d'ailleurs, vous pouvez remarquer que je l'ai utilisé dans mon code plus haut pour la fonction
init(). Il va sans dire que l'utilisation de
$this dans une classe abstraite s'ensuivra d'une belle erreur fatale, de la même façon que lorsqu'on essaie de l'instancier.
Code : Console | Fatal error: Using $this when not in object context in /srv/www/dev/tuto-abstract/abstract.php on line 8 |