dams Fri Jul 20 03:10:14 2001 EDT Modified files: /phpdoc/fr/language oop.xml Log: do_foo -> faire_foo
Index: phpdoc/fr/language/oop.xml diff -u phpdoc/fr/language/oop.xml:1.11 phpdoc/fr/language/oop.xml:1.12 --- phpdoc/fr/language/oop.xml:1.11 Mon Mar 19 12:06:31 2001 +++ phpdoc/fr/language/oop.xml Fri Jul 20 03:10:14 2001 @@ -1,5 +1,5 @@ <chapter id="language.oop"> - <title>Classes et objets</title> + <title>Les classes et les objets</title> <sect1 id="keyword.class"> <title>Les classes : <literal>class</literal></title> <para> @@ -34,6 +34,29 @@ tableau associatif contenant les articles du panier et de deux fonctions, une pour ajouter et une pour enlever des éléments au panier. </para> + <caution> + <simpara> + Les notes suivantes ne sont valable que pour PHP 4. + </simpara> + <simpara> + Le nom <literal>stdClass</literal> est utilisé en interne par + Zend et ne doit pas être utilisé. Vous ne pouvez pas nommer une + classe <literal>stdClass</literal> en PHP. + </simpara> + <simpara> + Les noms de fonctions <literal>__sleep</literal> et + <literal>__wakeup</literal> sont magiques en PHP. Vous ne pouvez + pas utiliser ces noms de fonctions dans vos classes, à moins + que vous ne souhaitiez utiliser la magie qui y est associée. + </simpara> + <simpara> + PHP se réserve l'usage de tous les noms de fonctions commençants +par + <literal>__</literal>, pour sa propre magie. Il est vivement + recommandé de ne pas utilser des noms de fonctions commençants par + <literal>__</literal>, à moins que vous ne souhaitiez utiliser + la magie qui y est associée. + </simpara> + </caution> <note> <simpara> En PHP 4, seuls les initialiseurs constants pour les variables @@ -49,19 +72,21 @@ var $date_du_jour = date("d/m/Y"); var $name = $firstname; var $owner = 'Fred ' . 'Jones'; + var $items = array("DVD", "Télé","Magnétoscope"); } /* Voici comment cela doit se faire désormais. */ class Caddie { var $date_du_jour; var $name; var $owner; + var $items; function Caddie() { $this->date_du_jour = date("d/m/Y"); $this->name = $GLOBALS['firstname']; /* etc... */ } } -?< +?> </programlisting> </informalexample> </note> @@ -74,21 +99,75 @@ <?php $cart = new Caddie; $cart->add_item("10", 1); + $another_cart = new Cart; + $another_cart->add_item("0815", 3); ?> </programlisting> </informalexample> <para> L'instruction ci-dessus crée l'objet $cart de la class Caddie. La fonction add_idem() est appelée afin d'ajouter l'article - numéro 10 dans la panier. + numéro 10 dans le panier. 3 articles numéro 0815 sont +ajoutés au + cart $another_cart. </para> <para> - Une classe peut être une extension d'une autre classe. - Les classes "extended" ou "derived" héritent de toutes - les variables et de toutes les fonctions de la classe père - plus toutes les définitions que vous rajoutez à cette - classe. Cela se fait avec le mot clef "extends". - L'héritage multiple n'est pas supporté. + $cart et $another_cart disposent des fonctions add_item(), + remove_item() et de la variable items. Ce sont des fonctions + et variables distinctes. Vous pouvez vous représenter les + objets comme des dossiers sur votre disque dur. Vous pouvez + avoir deux fichiers "lisez-moi.txt" sur votre disque dur, tant qu'ils + ne sont pas dans le même répertoire. De même que vous devez +alors + taper le chemin complet jusqu'au fichier, vous devez spécifier + le nom complet de la méthode avant de l'employer : en termes PHP, + le dossier racine est l'espace de nom global, et le séparateur + de dossier est <literal>-></literal>. Par exemple, les noms + $cart->items et $another_cart->items représentent deux + variables distinctes. Notez que le nom de la variable est alors + $cart->items, et non pas $cart->$items : il n'y a qu'un seul + signe $ dans un nom de variable. + </para> + <informalexample> + <programlisting role="php"> +<?php +// correct, $ unique +$cart->items = array("10" => 1); +// incorrect, car $cart->$items devient $cart->"" +$cart->$items = array("10" => 1); +// correct, mais risque de ne pas se comporter comme prévu +// $cart->$myvar devient $ncart->items +$myvar = 'items'; +$cart->$myvar = array("10" => 1); +?> + </programlisting> + </informalexample> + <para> + A l'intérieur d'une définition de classe, vous ne savez pas le + nom de la variable à partir duquel l'objet sera accessible dans + le script. On ne peut prévoir que l'objet créé sera +affecté à + la variable $cart ou $another_cart. Donc, vous ne pouvez pas + utiliser la syntaxe $cart->items. Mais pour pouvoir accéder à + aux méthodes et membres d'un objet, vous pouvez utiliser la variable + spéciale $this, qui peut s'interpréter comme 'moi-même', ou +bien + 'l'objet courant'. Par exemple, <literal>'$this->items[$artnr] += $num;'</literal> + peut se lire comme 'ajouter $num au compteur $artnr de mon propre tableau + de compteur' ou bien 'ajouter $num au compteur $artnr du tableau de compteurs + de l'objet courant'. + </para> + </sect1> + <sect1 id="keyword.extends"> + <title><literal>extends</literal> : héritage</title> + <para> + Souvent, vous aurez besoin d'une classe avec des méthodes et + fonctions similaires à une autre classe. En fait, il est bon + de définir des classes génériques, qui pourront être +réutilisées + et adaptées à tous vos projets. Pour faciliter cela, une + classe peut être une extension d'une autre classe. La classe + dérivée hérite alors de toutes les méthodes et +variables de + la classe de base (cet héritage a ça de bien que personne ne + meurt pour en profiter), mais peut définir ses propres fonctions + et variables, qui s'ajouteront. Une classe ne peut hériter que + d'une seule autre classe, et l'héritage multiple n'est pas + supporté. Les héritages se font avec le mot clé 'extends'. </para> <informalexample> <programlisting role="php"> @@ -122,31 +201,25 @@ ?> </programlisting> </informalexample> - <para> - Dans les fonctions d'une classe, la variable $this est - égale à l'objet de la classe. Vous pouvez - utilisez la forme "$this->quelquechose" pour accéder aux - fonctions ou aux variables de l'objet courant. Aussi bien - depuis l'objet lui-même que de l'extérieur, vous n'avez pas - besoin de <literal>$</literal> pour accéder aux - propriétés d'un objet. - </para> - <informalexample> - <programlisting role="php"> -<?php -$ncart->owner = "chris"; // pas de '$' -$ncart->$owner = "chris"; -// Ceci est invalide, car $ncart->$owner équivaut à $ncart->"" -$myvar = 'owner'; -$ncart->$myvar = "chris"; -// Ceci est valide, car $ncart->$owner équivaut à $ncart->owner - </programlisting> - </informalexample> + </sect1> + <sect1 id="language.oop.constructor"> + <title><literal>Constructor</literal> : constructeur</title> + <caution> + <simpara> + En PHP 3 et PHP 4, les constructeurs se comportent différemment. + La sémantique de PHP 4 est fortement recommandée. + </simpara> + </caution> <para> Le constructeur est la fonction qui est appelée automatiquement par la classe lorsque vous créez - une nouvelle instance d'une classe. La fonction constructeur a + une nouvelle instance d'une classe a l'aide de l'opérateur + <literal>new</literal>. La fonction constructeur a le même nom que la classe. + En PHP 3, une fonction devient le constructeur si elle porte le + même nom que la classe. En PHP 4, une fonction devient un constructeur + si elle porte le même nom que la classe dans laquelle elle est +définit. + La différence est subtile, mais cruciale. </para> <informalexample> <programlisting role="php"> @@ -156,43 +229,353 @@ $this->add_item ("10", 1); } } +// Cette syntaxe est valable en PHP 3 et 4 ?> </programlisting> </informalexample> - <para> + <para> L'exemple ci-dessus définit la classe Auto_Caddie qui hérite de la classe Caddie et définit le construteur de la classe. Ce dernier initialise le panier avec 1 article de type numéro 10 dès que l'instruction "new" est - appelée. La fonction constructeur peut prendre ou non, - des paramètres optionnels, ce qui la rend - beaucoup plus pratique. + appelée. La fonction constructeur peut prendre ou non + des paramètres optionnels, ce qui la rend beaucoup plus + pratique. Pour pouvoir utiliser cette classe sans paramètre, + tous les paramètres du constructeurs devraient être optionnels, + en fournissant une valeur par défaut, comme ci-dessous. </para> <informalexample> <programlisting role="php"> -<?php -class Constructor_Caddie extends Caddie { - function Constructor_Caddie ($item = "10", $num = 1) { +// Cette syntaxe est valable en PHP 3 et 4 +class Constructor_Cart extends Cart { + function Constructor_Cart ($item = "10", $num = 1) { $this->add_item ($item, $num); } } -// Place dans le caddie toujours la même chose... -$default_cart = new Constructor_Caddie; -// Place dans le caddie des objets différents, comme dans la -// réalité -$different_cart = new Constructor_Caddie ("20", 17); -?> +// Création du caddie +$default_cart = new Constructor_Cart; +// Création d'un vrai caddie +$different_cart = new Constructor_Cart ("20", 17); </programlisting> </informalexample> <caution> <simpara> - Pour les classes qui utilisent l'héritage, - le constructeur de la classe père n'est pas - automatiquement appelé lorsque le constructeur de la classe - dérivée est appelé. + En PHP 3, les classes dérivées et les constructeurs ont un certains + nombre de limitations. Les exemples suivants doivent être lus avec + beaucoup d'attention pour comprendre ces limitations. </simpara> </caution> + <informalexample> + <programlisting role="php"> +class A { + function A() { + echo "Je suis le constructeur de A.<br>\n"; + } +} +class B extends A { + function C() { + "Je suis une fonction standard.<br>\n"; + } +} +// Aucun constructeur n'est appelé en PHP 3!! +$b = new B; + </programlisting> + </informalexample> + <para> + En PHP 3, aucun constructeur ne sera appelé dans l'exemple ci-dessus. + La règle en PHP 3 est : 'Un constructeur est une fonction qui a le +même nom + que la classe'. Le nom de la classe est B, et il n'y a pas de fonctions qui + s'appelle B() dans la classe B. Rien ne se passe. + </para> + <para> + Ceci est corrigé en PHP 4, avec l'introduction d'une nouvelle règle +: + Si une classe n'a pas de constructeur, le constructeur de la classe de + basse est appelé, s'il existe. L'exemple ci-dessus affichera + 'Je suis le constructeur de A.<br>' en PHP 4. + </para> + <informalexample> + <programlisting role="php"> +class A { + function A() { + echo "Je suis le constructeur de A.<br>\n"; + } + function B() { + echo "Je suis une fonction standard appelée B dans la classe +A.<br>\n"; + echo "Je ne suis pas le constructeur de A.<br>\n"; + } +} +class B extends A { + function C() { + "Je suis une fonction standard.<br>\n"; + } +} +// Cette syntaxe va appeler B() comme constructeur. +$b = new B; + </programlisting> + </informalexample> + <para> + En PHP 3, la fonction B() de la classe A va soudaiement devenir le + constructeur de la classe B, bien qu'il n'ai pas été prévu +pour. + La règle de PHP 3 est 'Un constructeur est une fonction qui a le +même nom + que la classe'. PHP 3 ne se soucie guère si la fonction est définie + dans la classe B ou si elle a été héritée. + </para> + <para> + Ceci est corrigé en PHP 4, avec l'introduction d'une nouvelle règle +: + 'Un constructeur est une classe de même nom, définit dans la classe + elle-même'. Donc, en PHP 4, la classe B n'a pas de constructeur par +elle-même, + et le constructeur de la classe A aura été appelé, affichant +: + 'Je suis le constructeur de A.<br>'. + </para> + <caution> + <simpara> + Ni PHP 3 ni PHP 4 n'appelle automatiquement le constructeur de + la classe supérieure depuis le constructeur de la classe +dérivée. + Il est de votre responsabilité de propager l'appel des constructeurs. + </simpara> + </caution> + <note> + <simpara> + Il n'y a pas de destructeurs en PHP 3 et PHP 4. Vous pouvez utiliser + la fonction <function>register_shutdown_function</function> à la place, + pour simuler un destructeur. + </simpara> + </note> + <para> + Les destructeurs sont des fonctions qui sont appelées lorsqu'un + objet est détruit, soit avec la fonction <function>unset</function> + soit par simple sortie d'une fonction (cas des variables locales). + Il n'y a pas de destructeurs en PHP. + </para> </sect1> + <sect1 id="keyword.paamayim_nekudotayim"> + <title>Opérateur <literal>::</literal></title> + <caution> + <simpara> + La documentation suivante n'est valable que pour PHP 4. + </simpara> + </caution> + <para> + Parfois, il est pratique de faire référence aux fonctions + est variables d'une classe de base, ou bien d'utiliser + des méthodes de classes qui n'ont pas encore d'objets + créés. L'opérateur <literal>::</literal> est là pour +ces + situations. + </para> + <informalexample> + <programlisting role="php"> +<?php +class A { + function example() { + echo "Je suis la fonction originale A::example().<br>\n"; + } +} +class B extends A { + function example() { + echo "Je suis la fonction redéfinie B::example().<br>\n"; + A::example(); + } +} +// Il n'y a pas d'objets de classe A. +// L'affichage est : +// Je suis la fonction originale A::example().<br> +A::example(); +// Création d'un objet de la classe B. +$b = new B; +// L'affichage est : +// Je suis la fonction redéfinie B::example().<br> +// Je suis la fonction originale A::example().<br> +$b->example(); +?> + </programlisting> + </informalexample> + <para> + Les exemples ci-dessus appellent la fonction example() dans la + classe A, mais il n'y a pas encore d'objet de classe A, alors il + n'est pas possible d'écrire $a->example(). A la place, on appelle + la fonction example() comme une fonction de classe, c'est-à-dire + avec le nom de la classe elle-même, et sans objet. + </para> + <para> + Il y a des fonctions de classe, mais pas de variables de classe. + En fait, il n'y a aucun objet au moment de l'appel de la fonction. + Donc, une fonction de classe ne peut accéder à aucune variable + (mais elle peut accéder aux variables locales et globales). + Il faut proscire l'utilisation de $this. + </para> + <para> + Dans l'exemple ci-dessus, la classe B redéfinit la fonction example(). + La définition originale dans la classe A est remplacée par celle de + B, et n'est plus accessible depuis B, à moins que vous n'appeliez + spécifiquement la fonction example() de la classe A avec l'opérateur + ::. Ecrivez A::example() pour cela (en fait, il faudrait écrire + parent::example(), comme expliqué dans la section suivante). + </para> + <para> + Dans ce contexte, il y a un objet courant, qui peut avoir d'autres + variables objets. De ce fait, lorsqu'il est utilisé depuis une +méthode + d'un objet, vous pouvez utiliser $this. + </para> + </sect1> + <sect1 id="keyword.parent"> + <title><literal>parent</literal></title> + <para> + Il arrive que vous ayez à écrire du code qui faire +référence + aux variables et fonctions des classes de base. C'est particulièrement + vrai si votre classe dérivée est une spécialisation de votre +classe + de base. + </para> + <para> + Au lieu d'utiliser le nom litéral de votre classe de base dans + votre code, vous pouvez utiliser le mot réservé + <literal>parent</literal>, qui représente votre classe de + base (celle indiqué par <literal>extends</literal>, dans la +déclaration + de votre classe). En faisant cela, vous éviter d'appeler le + nom de votre classe de base directement dans votre code. + Si votre héritage change, vous n'aurez plus qu'à modifier + le nom de la classe dans la déclaration <literal>extends</literal> + de votre classe. + </para> + <informalexample> + <programlisting role="php"> +<?php +class A { + function example() { + echo "Je suis A::example() et je fournis une fonctionnalité de +base.<br>\n"; + } +} +class B extends A { + function example() { + echo "Je suis B::example() et je fournis une fonctionnalité +supplémentaire.<br>\n"; + parent::example(); + } +} +$b = new B; +// Cette syntaxe va appeler B::example(), qui, à sont tour, va appeler +A::example(). +$b->example(); +?> + </programlisting> + </informalexample> + </sect1> + <sect1 id="language.oop.serialization"> + <title>Sauvegarde d'objets - cas des sessions</title> + <note> + <simpara> + En PHP 3, les objets perdent leur association de classe à travers + le processus de sauvegarde et relecture. Le type de la variable après + relecture est bien objet mais il n'a plus de méthode ou de nom + de classe. Cela rend la focntionnalité plutôt inutile (l'objet + est devenu un tableau avec une syntaxe étrange). + </simpara> + </note> + <caution> + <simpara> + La documentation suivante n'est valable que pour PHP 4. + </simpara> + </caution> + <para> + <function>serialize</function> retourne une chaîne représentant + une valeur qui peut être stockée dans les sessions de PHP, ou une + base de données. <function>unserialize</function> peut relire cette + chaîne pour recréer la valeur originale. +<function>serialize</function> + va sauver toutes les variables d'un objet. Le nom de la classe sera + sauvé mais par les méthodes de cet objet. + </para> + <para> + Pour permettre à <function>unserialize</function> de lire un objet, + la classe de cet objet doit être définie. C'est-à-dire, si +vous avez + un objet $a de la classe A dans une page php1.php, et que vous le + linéarisez avec <function>serialize</function>, vous obtiendrez une + chaîne qui fait référence à la classe A, et contient +toutes les valeurs + de $a. Pour pouvoir le relire avec la fonction <function>unserialize</function> + dans une page page2.php, il faut que la définition de la classe + A soit présente dans cette deuxième page. Cela peut se faire + de manière pratique en sauvant la définition de la classe A dans un + fichier séparé, et en l'incluant dans les deux pages page1.php et + page2.php. + </para> + <informalexample> + <programlisting role="php"> +<?php +classa.inc: + class A { + var $one = 1; + function show_one() { + echo $this->one; + } + } +?> +page1.php: +<?php + include("classa.inc"); + $a = new A; + $s = serialize($a); + // enregistrez $s où la page2.php pourra le trouver. + $fp = fopen("store", "w"); + echo $s; + fclose($fp); +?> +page2.php: +<?php + // Ceci est nécessaire pour que unserialize() fonctionne correctement + include("classa.inc"); + $s = implode("", @file("store")); + unserialize($s); + // maintenant, utilisez la méthode show_one de l'objet $a. + $a->show_one(); +?> + </programlisting> + </informalexample> + <para> + Si vous utilisez les sessions et la fonction <function>session_register</function> + pour sauver des objets, ces objets seront linéarisés automatiquement + avec la fonction <function>serialize</function> à la fin de chaque + script, et relus avec <function>unserialize</function> au début du prochain + script. Cela signifie que ces objets peuvent apparaître dans n'importe quelle + page qui utilise vos sessions. + </para> + <para> + Il est vivement recommandé d'inclure la définition de classe dans + toutes vos pages, même si vous n'utilisez pas ces classes dans + toutes vos pages. Si vous l'oubliez et qu'un tel objet est + présent, il perdra sa classe, et deviendra un objet de classe + <literal>stdClass</literal> sans aucune fonction, et donc, plutôt + inutile. + </para> + <para> + Si, dans l'exemple ci-dessus, $a devient un objet de session + avec l'utilisation de <literal>session_register("a")</literal>, vous + devez pensez à inclure le fichier <literal>classa.inc</literal> dans toutes + vos pages, et pas seulement page1.php et page2.php. + </para> + </sect1> + <sect1 id="language.oop.magic-functions"> + <title>Les fonctions magiques <literal>__sleep</literal> et +<literal>__wakeup</literal></title> + <para> + <function>serialize</function> s'assure que votre classe a une méthode + avec le nom magique <literal>__sleep</literal>. Si c'est le cas, cette + fonction est appelée avant toute linéarisation. Elle peut alors +nettoyer + l'objet et on s'attend à ce qu'elle retourne un tableau avec la liste des + noms de variables qui doivent être sauvées. + </para> + <para> + Le but de cette fonction <literal>__sleep</literal> est de fermer + proprement toute connexion à une base de données, de valider les + requêtes, de finaliser toutes les actions commencées. Cette fonction + est aussi pratique si vous ave de très grands objets qui n'ont pas + besoin d'être sauvé entièrement. + </para> + <para> + A l'inverse, <function>unserialize</function> s'assure de la présence + de la fonction magique <literal>__wakeup</literal>. Si elle existe, cette + fonction reconstruit toutes les ressources d'un objet. + </para> + <para> + Le but de cette fonction <literal>__wakeup</literal> est de rétablit + toutes les connexions aux bases de données, et de recréer les + variables qui n'ont pas été sauvées. + </para> + </sect1> <sect1 id="keyword.newref"> <title>Références dans un constructeur</title> <para> @@ -249,7 +632,7 @@ </programlisting> </informalexample> <para> - Apparement, il n'y a pas de différence, mais en fait, il y en a une + Apparament, il n'y a pas de différence, mais en fait, il y en a une significative : <varname>$bar1</varname> et <varname>$globalref[0]</varname> ne sont pas référencées, ces deux variables sont différentes. Cela est du au fait que l'opérateur "new"ne retourne par de référence, @@ -260,9 +643,9 @@ référence) à retourner des copies au lieu de références. Au contraire, il est souvent mieux de travailler sur les copies plutôt que sur les références, car créer une référence prend un peu plus de temps que de créer une copie - qui ne prend virtuellement pas de temps (à moins qu'il ne se crée un - tableau géant ou un objet monstreux, auquel cas il est préférable de passer - par des références). + qui ne prend virtuellement pas de temps (à moins de créer un + tableau géant ou un objet monstreux, auquel cas il est + préférable de passer par des références). </simpara> </note> Pour prouver ceci, regardez le code suivant : @@ -270,9 +653,9 @@ <informalexample> <programlisting role="php"> <?php - // maintenant, nous allons changer de nom. Qu'attendez vous? + // maintenant, nous allons changer de nom. Qu'attendez-vous? // Vous pouvez vous attendre à ce que les deux variables $bar - // et $globalref[0] change de nom... + // et $globalref[0] changent de nom... $bar1->setName('modifié'); // comme prédit, ce n'est pas le cas $bar1->echoName(); @@ -321,7 +704,8 @@ } } // Essayez de comprendre pourquoi une copie simple va -// conduire à un résultat indésirable à la ligne marquée d'une étoile +// conduire à un résultat indésirable à +// la ligne marquée d'une étoile $a =&new a(10); $a->createRef(); $a->echoValue();