.\" Automatically generated by Pod::Man 2.06 (Pod::Simple 3.04)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sh \" Subsection heading
.br
.if t .Sp
.ne 5
.PP
\fB\\$1\fR
.PP
..
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. | will give a
.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to
.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C'
.\" expand to `' in nroff, nothing in troff, for use with C<>.
.tr \(*W-|\(bv\*(Tr
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
'br\}
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.if \nF \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. nr % 0
. rr F
.\}
.\"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.hy 0
.if n .na
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts.
. \" fudge factors for nroff and troff
.if n \{\
. ds #H 0
. ds #V .8m
. ds #F .3m
. ds #[ \f1
. ds #] \fP
.\}
.if t \{\
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
. ds #V .6m
. ds #F 0
. ds #[ \&
. ds #] \&
.\}
. \" simple accents for nroff and troff
.if n \{\
. ds ' \&
. ds ` \&
. ds ^ \&
. ds , \&
. ds ~ ~
. ds /
.\}
.if t \{\
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
. \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
. \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
. \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
. ds : e
. ds 8 ss
. ds o a
. ds d- d\h'-1'\(ga
. ds D- D\h'-1'\(hy
. ds th \o'bp'
. ds Th \o'LP'
. ds ae ae
. ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.IX Title "PERLBOOT 1"
.TH PERLBOOT 1 "2006-03-03" "DocFr" "User Contributed Perl Documentation"
.SH "NAME/NOM"
.IX Header "NAME/NOM"
perlboot \- Tutoriel pour l'oriente\*' objet a\*` destination des de\*'butants
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
Si vous n'e\*^tes pas familier avec les notions de programmation oriente\*'e objet
d'autres langages, certaines documentations concernant les objets en Perl
doivent vous sembler de\*'courageantes. Ces documents sont perlobj, la
re\*'fe\*'rence sur l'utilisation des objets, et perltoot qui pre\*'sente, sous
forme de tutoriel, les particularite\*'s des objets en Perl.
.PP
Ici nous utiliserons une approche diffe\*'rente en supposant que vous n'avez
aucune expe\*'rience pre\*'alable avec l'objet. Il est quand me\*^me souhaitable de
connai\*^tre les subroutines (perlsub), les re\*'fe\*'rences (perlref et autres)
et les paquetages (perlmod). Essayez de vous familiariser avec ces concepts
si vous ne l'avez pas de\*'ja\*` fait.
.Sh "Si nous pouvions parler aux animaux..."
.IX Subsection "Si nous pouvions parler aux animaux..."
Supposons un instant que les animaux parlent\ :
.PP
.Vb 9
\& sub Boeuf::fait {
\& print "un Boeuf fait mheuu !\en";
\& }
\& sub Cheval::fait {
\& print "un Cheval fait hiiii !\en";
\& }
\& sub Mouton::fait {
\& print "un Mouton fait be\*^e\*^e\*^ !\en"
\& }
\&
\& Boeuf::fait;
\& Cheval::fait;
\& Mouton::fait;
.Ve
.PP
Le re\*'sultat sera :
.PP
.Vb 3
\& un Boeuf fait mheuu !
\& un Cheval fait hiiii !
\& un Mouton fait be\*^e\*^e\*^ !
.Ve
.PP
Ici, rien de spectaculaire. De simples subroutines, bien que dans des paquetages
se\*'pare\*'s, appele\*'es en utilisant leur nom complet (incluant le nom du
paquetage). Cre\*'ons maintenant un troupeau\ :
.PP
.Vb 5
\& # Boeuf::fait, Cheval::fait, Mouton::fait comme au\-dessus
\& @troupeau = qw(Boeuf Boeuf Cheval Mouton Mouton);
\& foreach $animal (@troupeau) {
\& &{$animal."::fait"};
\& }
.Ve
.PP
Le re\*'sultat sera\ :
.PP
.Vb 5
\& un Boeuf fait mheuu !
\& un Boeuf fait mheuu !
\& un Cheval fait hiiii !
\& un Mouton fait be\*^e\*^e\*^ !
\& un Mouton fait be\*^e\*^e\*^ !
.Ve
.PP
Super. Mais l'utilisation de re\*'fe\*'rences symboliques vers les subroutines
\&\f(CW\*(C`fait\*(C'\fR est un peu de\*'plaisante. Nous comptons sur le mode \f(CW\*(C`no strict subs\*(C'\fR ce
qui n'est certainement pas recommande\*' pour de gros programmes. Et pourquoi
est-ce ne\*'cessaire\ ? Parce que le nom du paquetage semble inse\*'parable du
nom de la subroutine que nous voulons appeler dans ce paquetage.
.PP
L'est\-ce vraiment\ ?
.Sh "Pre\*'sentation de l'appel de me\*'thodes via l'ope\*'rateur fle\*`che"
.IX Subsection "Pre'sentation de l'appel de me'thodes via l'ope'rateur fle`che"
Pour l'instant, disons que \f(CW\*(C`Class\->method\*(C'\fR appelle la subroutine
\&\f(CW\*(C`method\*(C'\fR du paquetage \f(CW\*(C`Class\*(C'\fR. (Ici, X\ Class\ X est utilise\*' dans le
sens X\ cate\*'gorie\ X et non dans son sens
X\ universitaire\ X.) Ce n'est pas tout a\*` fait vrai mais allons-y
pas a\*` pas. Nous allons maintenant utiliser cela\ :
.PP
.Vb 4
\& # Boeuf::fait, Cheval::fait, Mouton::fait comme au\-dessus
\& Boeuf\->fait;
\& Cheval\->fait;
\& Mouton\->fait;
.Ve
.PP
A\*` nouveau, le re\*'sultat sera\ :
.PP
.Vb 3
\& un Boeuf fait mheuu !
\& un Cheval fait hiiii !
\& un Mouton fait be\*^e\*^e\*^ !
.Ve
.PP
Ce n'est pas encore super\ : me\*^me nombre de caracte\*`res, que des
constantes, pas de variables. Mais maintenant, on peut se\*'parer les
choses\ :
.PP
.Vb 2
\& $a = "Boeuf";
\& $a\->fait; # appelle Boeuf\->fait
.Ve
.PP
Ah\ ! Maintenant que le nom du paquetage est se\*'pare\*' du nom de la
subroutine, on peut utiliser un nom de paquetage variable. Et cette fois, nous
avons quelque chose qui marche me\*^me lorsque \f(CW\*(C`use strict refs\*(C'\fR est actif.
.Sh "Et pour tout un troupeau"
.IX Subsection "Et pour tout un troupeau"
Prenons ce nouvel appel via l'ope\*'rateur fle\*`che et appliquons-le dans l'exemple
du troupeau\ :
.PP
.Vb 9
\& sub Boeuf::fait {
\& print "un Boeuf fait mheuu !\en";
\& }
\& sub Cheval::fait {
\& print "un Cheval fait hiiii !\en";
\& }
\& sub Mouton::fait {
\& print "un Mouton fait be\*^e\*^e\*^ !\en"
\& }
\&
\& @troupeau = qw(Boeuf Boeuf Cheval Mouton Mouton);
\& foreach $animal (@troupeau) {
\& $animal\->fait;
\& }
.Ve
.PP
C\*,a y est\ ! Maintenant tous les animaux parlent et sans utiliser de
re\*'fe\*'rence symbolique.
.PP
Mais regardez tout ce code commun. Toutes les routines \f(CW\*(C`fait\*(C'\fR ont une
structure similaire\ : un ope\*'rateur \f(CW\*(C`print\*(C'\fR et une chai\*^ne qui contient
un texte identique, excepte\*'s deux mots. Ce serait inte\*'ressant de pouvoir
factoriser les parties communes au cas ou\*` nous de\*'ciderions plus tard de
changer \f(CW\*(C`fait\*(C'\fR en \f(CW\*(C`dit\*(C'\fR par exemple.
.PP
Il y a re\*'ellement moyen de le faire mais pour cela nous devons tout d'abord en
savoir un peu plus sur ce que l'ope\*'rateur fle\*`che peut faire pour nous.
.Sh "Le parame\*`tre implicite de l'appel de me\*'thodes"
.IX Subsection "Le parame`tre implicite de l'appel de me'thodes"
L'appel\ :
.PP
.Vb 1
\& Class\->method(@args)
.Ve
.PP
essaie d'appeler la subroutine \f(CW\*(C`Class::method\*(C'\fR de la manie\*`re suivante\ :
.PP
.Vb 1
\& Class::method("Class", @args);
.Ve
.PP
(Si la subroutine ne peut e\*^tre trouve\*'e, l'he\*'ritage intervient mais nous le
verrons plus tard.) Cela signifie que nous re\*'cupe\*'rons le nom de la classe
comme premier parame\*`tre (le seul parame\*`tre si aucun autre argument n'est
fourni). Donc nous pouvons re\*'e\*'crire la subroutine \f(CW\*(C`fait\*(C'\fR du \f(CW\*(C`Mouton\*(C'\fR
ainsi\ :
.PP
.Vb 4
\& sub Mouton::fait {
\& my $class = shift;
\& print "un $class fait be\*^e\*^e\*^ !\en";
\& }
.Ve
.PP
Et, de manie\*`re similaire, pour les deux autres animaux\ :
.PP
.Vb 8
\& sub Boeuf::fait {
\& my $class = shift;
\& print "un $class fait mheuu !\en";
\& }
\& sub Cheval::fait {
\& my $class = shift;
\& print "un $class fait hiiii !\en";
\& }
.Ve
.PP
Dans chaque cas, \f(CW$class\fR aura la valeur approprie\*'e pour la subroutine. Mais,
encore une fois, nous avons des structures similaires. Pouvons-nous factoriser
encore plus\ ? Oui, en appelant une autre me\*'thode de la me\*^me classe.
.Sh "Appel a\*` une seconde me\*'thode pour simplifier les choses"
.IX Subsection "Appel a` une seconde me'thode pour simplifier les choses"
Cre\*'ons donc une seconde me\*'thode nomme\*'e \f(CW\*(C`cri\*(C'\fR qui sera appele\*'e depuis
\&\f(CW\*(C`fait\*(C'\fR. Cette me\*'thode fournit un texte constant repre\*'sentant le cri lui\-me\*^me.
.PP
.Vb 7
\& { package Boeuf;
\& sub cri { "mheuu" }
\& sub fait {
\& my $class = shift;
\& print "un $class fait ", $class\->cri, " !\en"
\& }
\& }
.Ve
.PP
Maintenant, lorsque nous appelons \f(CW\*(C`Boeuf\->fait\*(C'\fR, \f(CW$class\fR vaut \f(CW\*(C`Boeuf\*(C'\fR
dans \f(CW\*(C`cri\*(C'\fR. Cela permet de choisir la me\*'thode \f(CW\*(C`Boeuf\->cri\*(C'\fR qui retourne
\&\f(CW\*(C`mheuu\*(C'\fR. Quelle diffe\*'rence voit-on dans la version correspondant au \f(CW\*(C`Cheval\*(C'\fR\ ?
.PP
.Vb 7
\& { package Cheval;
\& sub cri{ "hiiii" }
\& sub fait {
\& my $class = shift;
\& print "un $class fait ", $class\->cri, " !\en"
\& }
\& }
.Ve
.PP
Seuls le nom du paquetage et le cri changent. Pouvons-nous donc partager la
de\*'finition de \f(CW\*(C`fait\*(C'\fR entre le Boeuf et le Cheval ? Oui, gra\*^ce a\*`
l'he\*'ritage\ !
.Sh "L'he\*'ritage"
.IX Subsection "L'he'ritage"
Nous allons de\*'finir un paquetage commun appele\*' \f(CW\*(C`Animal\*(C'\fR contenant la de\*'finition
de \f(CW\*(C`fait\*(C'\fR\ :
.PP
.Vb 6
\& { package Animal;
\& sub fait {
\& my $class = shift;
\& print "un $class fait ", $class\->cri, " !\en"
\& }
\& }
.Ve
.PP
Puis nous allons demander a\*` chaque animal X\ d'he\*'riter\ X de
\&\f(CW\*(C`Animal\*(C'\fR\ :
.PP
.Vb 4
\& { package Boeuf;
\& @ISA = qw(Animal);
\& sub cri { "mheuu" }
\& }
.Ve
.PP
Remarquez l'ajout du tableau \f(CW@ISA\fR. Nous y reviendrons dans un instant...
.PP
Qu'arrive\-t\-il maintenant lorsque nous appelons \f(CW\*(C`Boeuf\->fait\*(C'\fR\ ?
.PP
Tout d'abord, Perl construit la liste d'arguments. Dans ce cas, c'est juste
\&\f(CW\*(C`Boeuf\*(C'\fR. Puis Perl cherche la subroutine \f(CW\*(C`Boeuf::fait\*(C'\fR. Mais elle n'existe
pas alors Perl regarde le tableau d'he\*'ritage \f(CW@Boeuf::ISA\fR. Il existe et
contient le seul nom \f(CW\*(C`Animal\*(C'\fR.
.PP
Perl cherche alors \f(CW\*(C`fait\*(C'\fR dans \f(CW\*(C`Animal\*(C'\fR, c'est a\*` dire \f(CW\*(C`Animal::fait\*(C'\fR. Comme
elle existe, Perl appelle cette subroutine avec la liste d'arguments
pre\*'\-calcule\*'e.
.PP
Dans la subroutine \f(CW\*(C`Animal::fait\*(C'\fR, \f(CW$class\fR vaut \f(CW\*(C`Boeuf\*(C'\fR (le premier et
seul argument). Donc, lorsque nous arrivons a\*` \f(CW\*(C`$class\->cri\*(C'\fR, la recherche
commence par \f(CW\*(C`Boeuf\->cri\*(C'\fR qui est trouve\*' au premier essai sans passage
par le tableau \f(CW@ISA\fR. C\*,a marche\ !
.ie n .Sh "Quelques remarques au sujet de @ISA"
.el .Sh "Quelques remarques au sujet de \f(CW@ISA\fP"
.IX Subsection "Quelques remarques au sujet de @ISA"
La variable magique \f(CW@ISA\fR (qui se prononce \- en anglais \- X\ is
a\ X et non X\ ice-uh\ X) de\*'clare que \f(CW\*(C`Boeuf\*(C'\fR est un
(X\ is a\ X) \f(CW\*(C`Animal\*(C'\fR. Notez bien que ce n'est pas une valeur mais
bien un tableau ce qui permet, en de rares occasions, d'avoir plusieurs
parents capables de fournir les me\*'thodes manquantes.
.PP
Si \f(CW\*(C`Animal\*(C'\fR a lui aussi un tableau \f(CW@ISA\fR, alors il est utilise\*' aussi. La
recherche est re\*'cursive, en profondeur d'abord et de gauche a\*` droite dans
chaque \f(CW@ISA\fR. Classiquement, chaque \f(CW@ISA\fR ne contient qu'un seul e\*'le\*'ment
(des e\*'le\*'ments multiples impliquent un he\*'ritage multiple et donc de multiples
casse\-te\*^te) ce qui de\*'finit un bel arbre d'he\*'ritage.
.PP
Lorsqu'on active \f(CW\*(C`use strict\*(C'\fR, on obtient un avertissement concernant \f(CW@ISA\fR
puisque c'est une variable dont le nom ne contient pas explicitement un nom de
paquetage et qui n'est pas de\*'clare\*'e comme une variable lexicale (via
X\ my\ X). On ne peut pas en faire une variable lexicale (car elle
doit appartenir au paquetage pour e\*^tre accessible au me\*'canisme
d'he\*'ritage). Voici donc plusieurs moyens de ge\*'rer cela\ :
.PP
Le moyen le plus simple est d'inclure explicitement le nom du paquetage\ :
.PP
.Vb 1
\& @Boeuf::ISA = qw(Animal);
.Ve
.PP
On peut aussi cre\*'er une variable de paquetage implicitement\ :
.PP
.Vb 3
\& package Boeuf;
\& use vars qw(@ISA);
\& @ISA = qw(Animal);
.Ve
.PP
Si vous pre\*'fe\*'rez une me\*'thode plus oriente\*'e objet, vous pouvez changer\ :
.PP
.Vb 4
\& package Boeuf;
\& use Animal;
\& use vars qw(@ISA);
\& @ISA = qw(Animal);
.Ve
.PP
en\ :
.PP
.Vb 2
\& package Boeuf;
\& use base qw(Animal);
.Ve
.PP
Ce qui est tre\*`s compact.
.Sh "Surcharge de me\*'thodes"
.IX Subsection "Surcharge de me'thodes"
Ajoutons donc un mulot qu'on peut a\*` peine entendre\ :
.PP
.Vb 10
\& # Paquetage Animal comme au\-dessus
\& { package Mulot;
\& @ISA = qw(Animal);
\& sub cri { "fiiik" }
\& sub fait {
\& my $class = shift;
\& print "un $class fait ", $class\->cri, " !\en";
\& print "[mais vous pouvez a\*` peine l'entendre !]\en";
\& }
\& }
\&
\& Mulot\->fait;
.Ve
.PP
Le re\*'sultat sera\ :
.PP
.Vb 2
\& un Mulot fait fiiik !
\& [mais vous pouvez a\*` peine l'entendre !]
.Ve
.PP
Ici, \f(CW\*(C`Mulot\*(C'\fR a sa propre routine cri, donc \f(CW\*(C`Mulot\->fait\*(C'\fR n'appellera pas
imme\*'diatement \f(CW\*(C`Animal\->fait\*(C'\fR. On appelle cela la surcharge
(X\ overridding\ X en anglais). En fait, nous n'avons pas besoin du
tout de dire qu'un \f(CW\*(C`Mulot\*(C'\fR est un \f(CW\*(C`Animal\*(C'\fR puisque toutes les me\*'thodes
ne\*'cessaires a\*` \f(CW\*(C`fait\*(C'\fR sont de\*'finies par \f(CW\*(C`Mulot\*(C'\fR.
.PP
Mais maintenant nous avons duplique\*' le code de \f(CW\*(C`Animal\->fait\*(C'\fR et cela
peut nous amener a\*` des proble\*`mes de maintenance. Alors, pouvons-nous
l'e\*'viter\ ? Pouvons-nous dire qu'un \f(CW\*(C`Mulot\*(C'\fR fait exactement comme un
autre \f(CW\*(C`Animal\*(C'\fR mais en ajoutant un commentaire en plus\ ? Oui\ !
.PP
Tout d'abord, nous pouvons appeler directement la me\*'thode
\&\f(CW\*(C`Animal::fait\*(C'\fR\ :
.PP
.Vb 10
\& # Paquetage Animal comme au\-dessus
\& { package Mulot;
\& @ISA = qw(Animal);
\& sub cri { "fiiik" }
\& sub fait {
\& my $class = shift;
\& Animal::fait($class);
\& print "[mais vous pouvez a\*` peine l'entendre !]\en";
\& }
\& }
.Ve
.PP
Remarquez que nous sommes oblige\*'s d'inclure le parame\*`tre \f(CW$class\fR (qui doit
certainement valoir \f(CW\*(C`Mulot\*(C'\fR) comme premier parame\*`tre de \f(CW\*(C`Animal::fait\*(C'\fR
puisque nous n'utilisons plus l'ope\*'rateur fle\*`che. Pourquoi ne plus
l'utiliser\ ? Si nous appelons \f(CW\*(C`Animal\->fait\*(C'\fR ici, le premier
parame\*`tre de la me\*'thode sera \f(CW"Animal"\fR et non \f(CW"Mulot"\fR et lorsqu'on
arrivera a\*` l'appel de \f(CW\*(C`cri\*(C'\fR, nous n'aurons pas la bonne classe.
.PP
L'invocation directe de \f(CW\*(C`Animal::fait\*(C'\fR est tout autant proble\*'matique. Que se
passe-t-il si la subroutine \f(CW\*(C`Animal::fait\*(C'\fR n'existe pas et est en fait
he\*'rite\*'e d'une classe mentionne\*'e dans \f(CW@Animal::ISA\fR\ ? Puisque nous
n'utilisons pas l'ope\*'rateur fle\*`che, nous n'avons pas la moindre chance que
cela fonctionne.
.PP
Notez aussi que le nom de la classe \f(CW\*(C`Animal\*(C'\fR est maintenant code\*'e
explicitement pour choisir la bonne subroutine. Ce sera un proble\*`me pour celui
qui changera le tableau \f(CW@ISA\fR de \f(CW\*(C`Mulot\*(C'\fR sans remarquer que \f(CW\*(C`Animal\*(C'\fR est
utilise\*' explicitement dans \f(CW\*(C`fait\*(C'\fR. Ce n'est donc pas la bonne me\*'thode.
.Sh "Effectuer la recherche a\*` partir d'un point diffe\*'rent"
.IX Subsection "Effectuer la recherche a` partir d'un point diffe'rent"
Une meilleure solution consiste a\*` demander a\*` Perl de rechercher dans la chai\*^ne
d'he\*'ritage un cran plus haut\ :
.PP
.Vb 9
\& # Animal comme au\-dessus
\& { package Mulot;
\& # me\*^me @ISA et me\*^me &cri qu'au\-dessus
\& sub fait {
\& my $class = shift;
\& $class\->Animal::fait;
\& print "[mais vous pouvez a\*` peine l'entendre !]\en";
\& }
\& }
.Ve
.PP
C\*,a marche. En utilisant cette syntaxe, nous commenc\*,ons par chercher dans
\&\f(CW\*(C`Animal\*(C'\fR pour trouver \f(CW\*(C`fait\*(C'\fR et nous utilisons toute la chai\*^ne d'he\*'ritage de
\&\f(CW\*(C`Animal\*(C'\fR si on ne la trouve pas tout de suite. Et comme le premier argument
sera \f(CW$class\fR, la me\*'thode \f(CW\*(C`fait\*(C'\fR trouve\*'e pourra e\*'ventuellement appeler
\&\f(CW\*(C`Mulot::cri\*(C'\fR.
.PP
Mais ce n'est pas la meilleure solution. Nous avons encore a\*` coordonner le
tableau \f(CW@ISA\fR et le nom du premier paquetage de recherche. Pire, si \f(CW\*(C`Mulot\*(C'\fR a
plusieurs entre\*'es dans son tableau \f(CW@ISA\fR, nous ne savons pas ne\*'cessairement
laquelle de\*'finit re\*'ellement \f(CW\*(C`fait\*(C'\fR. Alors, y a\-t-il une meilleure
solution\ ?
.Sh "Le \s-1SUPER\s0 moyen de faire des choses"
.IX Subsection "Le SUPER moyen de faire des choses"
En changeant la classe \f(CW\*(C`Animal\*(C'\fR par la classe \f(CW\*(C`SUPER\*(C'\fR, nous obtenons
automatiquement une recherche dans toutes les \s-1SUPER\s0 classes (les classes
liste\*'es dans \f(CW@ISA\fR)\ :
.PP
.Vb 9
\& # Animal comme au dessus
\& { package Mulot;
\& # me\*^me @ISA et me\*^me &cri qu'au dessus
\& sub dir {
\& my $class = shift;
\& $class\->SUPER::fait;
\& print "[mais vous pouvez a\*` peine l'entendre !]\en";
\& }
\& }
.Ve
.PP
Donc, \f(CW\*(C`SUPER::fait\*(C'\fR signifie qu'il faut chercher la subroutine \f(CW\*(C`fait\*(C'\fR dans
les paquetages liste\*'s par le tableau \f(CW@ISA\fR du paquetage courant (en commenc\*,ant
par le premier). Notez bien que la recherche \fIne\fR sera \fIpas\fR faite dans le
tableau \f(CW@ISA\fR de \f(CW$class\fR.
.Sh "Ou\*` en sommes-nous ?"
.IX Subsection "Ou` en sommes-nous ?"
Jusqu'ici, nous avons vu la syntaxe d'appel des me\*'thodes via la fle\*`che\ :
.PP
.Vb 1
\& Class\->method(@args);
.Ve
.PP
ou son e\*'quivalent\ :
.PP
.Vb 2
\& $a = "Class";
\& $a\->method(@args);
.Ve
.PP
qui construit la liste d'argument\ :
.PP
.Vb 1
\& ("Class", @args)
.Ve
.PP
et essaye d'appeler\ :
.PP
.Vb 1
\& Class::method("Class", @args);
.Ve
.PP
Si \f(CW\*(C`Class::method\*(C'\fR n'est pas trouve\*'e, alors le tableau \f(CW@Class::ISA\fR est
utilise\*' (re\*'cursivement) pour trouver un paquetage qui propose \f(CW\*(C`method\*(C'\fR puis la
me\*'thode est appele\*'e.
.PP
En utilisant cette simple syntaxe, nous avons des me\*'thodes de classes avec
he\*'ritage (multiple), surcharge et extension. Et nous avons e\*'te\*' capable de
factoriser tout le code commun tout en fournissant un moyen propre de
re\*'utiliser l'imple\*'mentation avec des variantes. C'est ce que fournit le coeur
de la programmation oriente\*'e objet mais les objets peuvent aussi fournir des
donne\*'es d'instances que nous n'avons pas encore vues.
.Sh "Un cheval est un cheval bien su\*^r... Mais n'est\-il que cela ?"
.IX Subsection "Un cheval est un cheval bien su^r... Mais n'est-il que cela ?"
Repartons donc du code de la classe \f(CW\*(C`Animal\*(C'\fR et de la classe
\&\f(CW\*(C`Cheval\*(C'\fR\ :
.PP
.Vb 10
\& { package Animal;
\& sub fait {
\& my $class = shift;
\& print "un $class fait ", $class\->cri, " !\en"
\& }
\& }
\& { package Cheval;
\& @ISA = qw(Animal);
\& sub cri { "hiiii" }
\& }
.Ve
.PP
Cela permet d'appeler \f(CW\*(C`Cheval\->fait\*(C'\fR qui est en fait \f(CW\*(C`Animal::fait\*(C'\fR qui,
elle\-me\*^me appelle en retour \f(CW\*(C`Cheval::cri\*(C'\fR pour obtenir le cri spe\*'cifique. Ce
qui produit\ :
.PP
.Vb 1
\& un Cheval fait hiiii !
.Ve
.PP
Mais tous nos objets Cheval (Chevaux ;\-) doivent absolument e\*^tre
identiques. Si j'ajoute une subroutine, tous les chevaux la partagent
automatiquement. C'est tre\*`s bien pour faire des chevaux identiques mais,
alors, comment faire pour distinguer les chevaux les uns des autres\ ?
Par exemple, supposons que nous voulions donner un nom au premier cheval. Il
nous faut un moyen de conserver son nom inde\*'pendamment des autres chevaux.
.PP
Nous pouvons le faire en introduisant une nouvelle notion appele\*'e
X\ instance\ X. Une X\ instance\ X est ge\*'ne\*'ralement cre\*'e\*'e
par une classe. En Perl, n'importe quelle re\*'fe\*'rence peut e\*^tre une
instance. Commenc\*,ons donc par la plus simple des re\*'fe\*'rences qui peut stocker
le nom d'un cheval\ : une re\*'fe\*'rence sur un scalaire.
.PP
.Vb 2
\& my $nom = "Mr. Ed";
\& my $parleur = \e$nom;
.Ve
.PP
Maintenant \f(CW$parleur\fR est une re\*'fe\*'rence vers ce qui sera une donne\*'e
spe\*'cifique de l'instance (le nom). L'e\*'tape finale consiste a\*` la transformer en
une vraie instance gra\*^ce a\*` l'ope\*'rateur appele\*' \f(CW\*(C`bless\*(C'\fR (\fIbe\*'nir\fR ou
\&\fIconsacrer\fR en anglais)\ :
.PP
.Vb 1
\& bless $parleur, Cheval;
.Ve
.PP
Cet ope\*'rateur associe le paquetage nomme\*' \f(CW\*(C`Cheval\*(C'\fR a\*` ce qui est pointe\*' par la
re\*'fe\*'rence. A\*` partir de ce moment, on peut dire que \f(CW$parleur\fR est une
instance de \f(CW\*(C`Cheval\*(C'\fR. C'est a\*` dire que c'est un \f(CW\*(C`Cheval\*(C'\fR spe\*'cifique. La
re\*'fe\*'rence en tant que telle n'est pas modifie\*'e et on peut continuer a\*`
l'utiliser avec les ope\*'rateurs traditionnels de de\*'re\*'fe\*'rencement.
.Sh "Appel d'une me\*'thode d'instance"
.IX Subsection "Appel d'une me'thode d'instance"
L'appel de me\*'thodes via l'ope\*'rateur fle\*`che peut e\*^tre utilise\*' sur des instances
exactement comme on le fait avec un nom de paquetage (classe). Donc, cherchons
le cri que \f(CW$parleur\fR fait\ :
.PP
.Vb 1
\& my $bruit = $parleur\->cri;
.Ve
.PP
Pour appeler \f(CW\*(C`cri\*(C'\fR, Perl remarque tout d'abord que \f(CW$parleur\fR est une
re\*'fe\*'rence consacre\*'e (via \fIbless()\fR) et donc une instance. Ensuite, il construit
la liste des arguments qui, dans ce cas, n'est que \f(CW$parleur\fR. (Plus tard,
nous verrons que les autres arguments suivent la variable d'instance
exactement comme avec les classes.)
.PP
Maintenant la partie inte\*'ressante\ : Perl re\*'cupe\*`re la classe ayant
consacre\*'e l'instance, dans notre cas \f(CW\*(C`Cheval\*(C'\fR, et l'utilise pour trouver la
subroutine a\*` appeler. Dans notre cas, \f(CW\*(C`Cheval::cri\*(C'\fR est trouve\*'e directement
(sans utiliser d'he\*'ritage) et cela nous ame\*`ne a\*` l'appel finale de la
subroutine\ :
.PP
.Vb 1
\& Cheval::cri($parleur)
.Ve
.PP
Remarquez que le premier parame\*`tre est bien l'instance et non le nom de la
classe comme auparavant. Nous obtenons \f(CW\*(C`hiiii\*(C'\fR comme valeur de retour et
cette valeur est stocke\*'e dans la variable \f(CW$bruit\fR.
.PP
Si \f(CW\*(C`Cheval::cri\*(C'\fR n'avait pas existe\*', nous aurions e\*'te\*' oblige\*' d'explorer
\&\f(CW@Cheval::ISA\fR pour y rechercher cette subroutine dans l'une des
super-classes exactement comme avec les me\*'thodes de classes. La seule
diffe\*'rence entre une me\*'thode de classe et une me\*'thode d'instance est le
premier argument qui est soit un nom de classe (une chai\*^ne) soit une instance
(une re\*'fe\*'rence consacre\*'e).
.Sh "Acce\*`s aux donne\*'es d'instance"
.IX Subsection "Acce`s aux donne'es d'instance"
Puisque nous avons une instance comme premier parame\*`tre, nous pouvons acce\*'der
aux donne\*'es spe\*'cifiques de l'instance. Dans notre cas, ajoutons un moyen
d'obtenir le nom\ :
.PP
.Vb 8
\& { package Cheval;
\& @ISA = qw(Animal);
\& sub cri { "hiiii" }
\& sub nom {
\& my $self = shift;
\& $$self;
\& }
\& }
.Ve
.PP
Maintenant, appelons cette me\*'thode\ :
.PP
.Vb 1
\& print $parleur\->nom, " fait ", $parleur\->cri, "\en";
.Ve
.PP
Dans \f(CW\*(C`Cheval::nom\*(C'\fR, le tableau \f(CW@_\fR contient juste \f(CW$parleur\fR que \f(CW\*(C`shift\*(C'\fR
stocke dans \f(CW$self\fR. (Il est classique de de\*'piler le premier parame\*`tre dans
une variable nomme\*'e \f(CW$self\fR pour les me\*'thodes d'instance. Donc conservez cela
tant que vous n'avez pas de bonnes raisons de faire autrement.) Puis, \f(CW$self\fR
est de\*'re\*'fe\*'rence\*' comme un scalaire pour obtenir \f(CW\*(C`Mr. Ed\*(C'\fR. Le re\*'sultat
sera\ :
.PP
.Vb 1
\& Mr. Ed fait hiiii
.Ve
.Sh "Comment fabriquer un cheval"
.IX Subsection "Comment fabriquer un cheval"
Bien su\*^r, si nous construisons tous nos chevaux a\*` la main, nous ferons des
erreurs de temps en temps. Nous violons aussi l'un des principes de la
programmation oriente\*'e objet puisque les X\ entrailles\ X d'un
cheval sont visibles. C'est bien si nous sommes ve\*'te\*'rinaire pas si nous sommes
de simples proprie\*'taires de chevaux. Laissons donc la classe Cheval fabriquer
elle\-me\*^me un nouveau cheval\ :
.PP
.Vb 10
\& { package Cheval;
\& @ISA = qw(Animal);
\& sub cri { "hiiii" }
\& sub nom {
\& my $self = shift;
\& $$self;
\& }
\& sub nomme {
\& my $class = shift;
\& my $nom = shift;
\& bless \e$nom, $class;
\& }
\& }
.Ve
.PP
Maintenant, gra\*^ce a\*` la me\*'thode \f(CW\*(C`nomme\*(C'\fR, nous pouvons cre\*'er un cheval\ :
.PP
.Vb 1
\& my $parleur = Cheval\->nomme("Mr. Ed");
.Ve
.PP
Remarquez que nous sommes revenus a\*` une me\*'thode de classe donc les deux
arguments de \f(CW\*(C`Cheval::nomme\*(C'\fR sont \f(CW\*(C`Cheval\*(C'\fR et \f(CW\*(C`Mr. Ed\*(C'\fR. L'ope\*'rateur
\&\f(CW\*(C`bless\*(C'\fR en plus de consacrer \f(CW$nom\fR retourne une re\*'fe\*'rence a\*` \f(CW$nom\fR qui
est parfaite comme valeur de retour. Et c'est comme cela qu'on construit un
cheval.
.PP
Ici, nous avons appele\*' le constructeur \f(CW\*(C`nomme\*(C'\fR ce qui indique que l'argument
de ce constructeur est le nom de ce \f(CW\*(C`Cheval\*(C'\fR particulier. Vous pouvez
utiliser diffe\*'rents constructeurs avec diffe\*'rents noms pour avoir des moyens
diffe\*'rents de X\ donner naissance\ X a\*` un objet. En revanche, vous
constaterez que de nombreuses personnes qui sont venues a\*` Perl a\*` partir de
langages plus limite\*'s n'utilisent qu'un seul constructeur appele\*' \f(CW\*(C`new\*(C'\fR avec
plusieurs fac\*,ons d'interpre\*'ter ses arguments. Tous les styles sont corrects
tant que vous documentez (et vous le ferez, n'est\-ce pas\ ?) le moyen de
donner naissance a\*` votre objet.
.Sh "He\*'ritage de constructeur"
.IX Subsection "He'ritage de constructeur"
Mais y a\-t-il quelque chose de spe\*'cifique au \f(CW\*(C`Cheval\*(C'\fR dans cette
me\*'thode\ ? Non. Par conse\*'quent, c'est la me\*^me chose pour construire
n'importe quoi qui he\*'rite d'un \f(CW\*(C`Animal\*(C'\fR. Plac\*,ons donc cela dans
\&\f(CW\*(C`Animal\*(C'\fR\ :
.PP
.Vb 10
\& { package Animal;
\& sub fait {
\& my $class = shift;
\& print "un $class fait ", $class\->cri, " !\en"
\& }
\& sub nom {
\& my $self = shift;
\& $$self;
\& }
\& sub nomme {
\& my $class = shift;
\& my $nom = shift;
\& bless \e$nom, $class;
\& }
\& }
\& { package Cheval;
\& @ISA = qw(Animal);
\& sub cri { "hiiii" }
\& }
.Ve
.PP
Bon. Mais que se passe-t-il si nous appelons \f(CW\*(C`fait\*(C'\fR depuis une
instance\ ?
.PP
.Vb 2
\& my $parleur = Cheval\->nomme("Mr. Ed");
\& $parleur\->fait;
.Ve
.PP
Nous obtenons le texte suivant\ :
.PP
.Vb 1
\& un Cheval=SCALAR(0xaca42ac) fait hiiii !
.Ve
.PP
Pourquoi\ ? Parce que la routine \f(CW\*(C`Animal::fait\*(C'\fR s'attend a\*` recevoir un
nom de classe comme premier parame\*`tre et non une instance. Lorsqu'une instance
est passe\*'e, nous nous retrouvons a\*` utiliser un re\*'fe\*'rence consacre\*'e a\*` un
scalaire en tant que chai\*^ne et nous obtenons ce que nous venons de voir.
.Sh "Concevoir une me\*'thode qui marche aussi bien avec des instances qu'avec des classes"
.IX Subsection "Concevoir une me'thode qui marche aussi bien avec des instances qu'avec des classes"
Tout ce dont nous avons besoin c'est de de\*'tecter si l'appel se fait via une
classe ou via une instance. Le moyen le plus simple est d'utiliser l'ope\*'rateur
\&\f(CW\*(C`ref\*(C'\fR. Il retourne une chai\*^ne (le nom de la classe) lorsqu'il est applique\*'
sur une re\*'fe\*'rence consacre\*'e et \f(CW\*(C`undef\*(C'\fR lorsqu'il est applique\*' a\*` une chai\*^ne
(comme un nom de classe). Modifions donc la me\*'thode \f(CW\*(C`nom\*(C'\fR pour prendre cela
en compte\ :
.PP
.Vb 6
\& sub nom {
\& my $classouref = shift;
\& ref $classouref
\& ? $$classouref # c'est une instance, on retourne le nom
\& : "un $classouref anonyme"; # c'est une classe, on retourne un nom ge\*'ne\*'rique
\& }
.Ve
.PP
Ici, l'ope\*'rateur \f(CW\*(C`?:\*(C'\fR devient le moyen de choisir entre de\*'re\*'fe\*'rencement ou
chai\*^ne. Maintenant nous pouvons utiliser notre me\*'thode indiffe\*'remment avec une
classe ou avec une instance. Notez que nous avons transforme\*' le premier
parame\*`tre en \f(CW$classouref\fR pour indiquer ce qu'il contient\ :
.PP
.Vb 3
\& my $parleur = Cheval\->nomme("Mr. Ed");
\& print Cheval\->nom, "\en"; # affiche "un Cheval anonyme\en"
\& print $parleur\->nom, "\en"; # affiche "Mr. Ed\en"
.Ve
.PP
Modifions \f(CW\*(C`fait\*(C'\fR pour utiliser \f(CW\*(C`nom\*(C'\fR\ :
.PP
.Vb 4
\& sub fait {
\& my $classouref = shift;
\& print $classouref\->nom, " fait ", $classouref\->cri, "\en";
\& }
.Ve
.PP
Et puisque \f(CW\*(C`cri\*(C'\fR fonctionne de\*'ja\*` que ce soit avec une instance ou une classe,
nous avons fini\ !
.Sh "Ajout de parame\*`tres aux me\*'thodes"
.IX Subsection "Ajout de parame`tres aux me'thodes"
Faisons manger nos animaux\ :
.PP
.Vb 10
\& { package Animal;
\& sub nomme {
\& my $class = shift;
\& my $nom = shift;
\& bless \e$nom, $class;
\& }
\& sub nom {
\& my $classouref = shift;
\& ref $classouref
\& ? $$classouref # c'est une instance, on retourne le nom
\& : "un $classouref anonyme"; # c'est une classe, on retourne un nom ge\*'ne\*'rique
\& }
\& sub fait {
\& my $classouref = shift;
\& print $classouref\->nom, " fait ", $classouref\->cri, "\en";
\& }
\& sub mange {
\& my $classouref = shift;
\& my $nourriture = shift;
\& print $classouref\->nom, " mange $nourriture.\en";
\& }
\& }
\& { package Cheval;
\& @ISA = qw(Animal);
\& sub cri { "hiiii" }
\& }
\& { package Mouton;
\& @ISA = qw(Animal);
\& sub cri { "be\*^e\*^e\*^" }
\& }
.Ve
.PP
Essayons ce code\ :
.PP
.Vb 3
\& my $parleur = Cheval\->nomme("Mr. Ed");
\& $parleur\->mange("du foin");
\& Mouton\->mange("de l'herbe");
.Ve
.PP
qui affiche\ :
.PP
.Vb 2
\& Mr. Ed mange du foin.
\& un Mouton anonyme mange de l'herbe.
.Ve
.PP
Une me\*'thode d'instance avec des parame\*`tres est appele\*' avec, comme parame\*`tres,
l'instance puis la liste des parame\*`tres. Donc ici, le premier appel est
comme\ :
.PP
.Vb 1
\& Animal::mange($parleur, "du foin");
.Ve
.Sh "Des instances plus inte\*'ressantes"
.IX Subsection "Des instances plus inte'ressantes"
Comment faire pour qu'une instance posse\*`de plus de donne\*'es\ ? Les
instances les plus inte\*'ressantes sont constitue\*'es de plusieurs e\*'le\*'ments qui
peuvent e\*^tre eux\-me\*^mes des re\*'fe\*'rences ou me\*^me des objets. Le moyen le plus
simple pour les stocker est souvent une table de hachage. Les cle\*'s de la table
de hachage servent a\*` nommer ces diffe\*'rents e\*'le\*'ments (qu'on appelle souvent
X\ variables d'instance\ X ou X\ variables membres\ X) et
les valeurs attache\*'es sont... les valeurs de ces e\*'le\*'ments.
.PP
Mais comment transformer notre cheval en une table de hachage\ ?
Rappelez-vous qu'un objet est une re\*'fe\*'rence consacre\*'e. Il est tout a\*` fait
possible d'utiliser une re\*'fe\*'rence consacre\*'e vers une table de hachage pluto\*^t
que vers un simple scalaire a\*` partir du moment ou\*` chaque acce\*`s au contenu de
cette re\*'fe\*'rence l'utilise correctement.
.PP
Cre\*'ons un mouton avec un nom et une couleur\ :
.PP
.Vb 1
\& my $mauvais = bless { Nom => "Evil", Couleur => "noir" }, Mouton;
.Ve
.PP
Ainsi \f(CW\*(C`$mauvais\->{Nom}\*(C'\fR donne et \f(CW\*(C`Evil\*(C'\fR et \f(CW\*(C`$mauvais\->{Couleur}\*(C'\fR
donne \f(CW\*(C`Noir\*(C'\fR. Mais \f(CW\*(C`$mauvais\->nom\*(C'\fR doit donner le nom et cela ne marche
plus car cette me\*'thode attend une re\*'fe\*'rence vers un simple scalaire. Ce n'est
pas tre\*`s grave car c'est simple a\*` corriger\ :
.PP
.Vb 7
\& ## dans Animal
\& sub nom {
\& my $classouref = shift;
\& ref $classouref ?
\& $classouref\->{Nom} :
\& "un $classouref anonyme";
\& }
.Ve
.PP
Bien su\*^r, \f(CW\*(C`nomme\*(C'\fR construit encore un mouton avec une re\*'fe\*'rence vers un
scalaire. Corrigeons la\*` aussi\ :
.PP
.Vb 7
\& ## dans Animal
\& sub nomme {
\& my $class = shift;
\& my $nom = shift;
\& my $self = { Nom => $nom, Couleur => $class\->couleur_defaut };
\& bless $self, $class;
\& }
.Ve
.PP
D'ou\*` vient ce \f(CW\*(C`couleur_defaut\*(C'\fR\ ? Eh bien, puisque \f(CW\*(C`nomme\*(C'\fR ne fournit
que le nom, nous devons encore de\*'finir une couleur. Nous avons donc une
couleur par de\*'faut pour la classe. Pour un mouton, nous pouvons la de\*'finir a\*`
blanc\ :
.PP
.Vb 2
\& ## dans Mouton
\& sub couleur_defaut { "blanc" }
.Ve
.PP
Et pour nous e\*'viter de de\*'finir une couleur par de\*'faut pour toutes les classes,
nous allons de\*'finir aussi une me\*'thode ge\*'ne\*'rale dans \f(CW\*(C`Animal\*(C'\fR qui servira de
X\ couleur par de\*'faut\ X par de\*'faut\ :
.PP
.Vb 2
\& ## dans Animal
\& sub couleur_defaut { "marron" }
.Ve
.PP
Comme \f(CW\*(C`nom\*(C'\fR et \f(CW\*(C`nomme\*(C'\fR e\*'taient les seules me\*'thodes qui utilisaient
explicitement la X\ structure\ X des objets, toutes les autres
me\*'thodes restent inchange\*'es et donc \f(CW\*(C`fait\*(C'\fR fonctionne encore comme avant.
.Sh "Des chevaux de couleurs diffe\*'rentes"
.IX Subsection "Des chevaux de couleurs diffe'rentes"
Des chevaux qui sont tous de la me\*^me couleur sont ennuyeux. Alors ajoutons une
me\*'thode ou deux afin de choisir la couleur.
.PP
.Vb 7
\& ## dans Animal
\& sub couleur {
\& $_[0]\->{Couleur}
\& }
\& sub set_couleur {
\& $_[0]\->{Couleur} = $_[1];
\& }
.Ve
.PP
Remarquez un autre moyen d'utiliser les arguments\ : \f(CW$_[0]\fR est utilise\*'
directement pluto\*^t que via un \f(CW\*(C`shift\*(C'\fR. (Cela e\*'conomise un tout petit peu de
temps pour quelque chose qui peut e\*^tre invoque\*' fre\*'quemment.) Maintenant, on
peut choisir la couleur de Mr. Ed\ :
.PP
.Vb 3
\& my $parleur = Cheval\->nomme("Mr. Ed");
\& $parleur\->set_couleur("noir\-et\-blanc");
\& print $parleur\->nom, " est de couleur ", $parleur\->couleur, "\en";
.Ve
.PP
qui donne\ :
.PP
.Vb 1
\& Mr. Ed est de couleur noir\-et\-blanc
.Ve
.Sh "Re\*'sume\*'"
.IX Subsection "Re'sume'"
Ainsi, maintenant nous avons des me\*'thodes de classe, des constructeurs, des
me\*'thodes d'instances, des donne\*'es d'instances, et e\*'galement des accesseurs.
Mais cela n'est que le de\*'but de ce que Perl peut offrir. Nous n'avons pas non
plus commence\*' a\*` parler des accesseurs qui fonctionnent a\*` la fois en lecture et
en e\*'criture, des destructeurs, de la notation d'objets indirects, des
sous-classes qui ajoutent des donne\*'es d'instances, des donne\*'es de classe, de
la surcharge, des tests X\ isa\ X et X\ can\ X de la
classe \f(CW\*(C`UNIVERSAL\*(C'\fR, et ainsi de suite. C'est couvert par le reste de la
documentation de Perl. En espe\*'rant que cela vous permette de de\*'marrer,
vraiment.
.SH "VOIR AUSSI"
.IX Header "VOIR AUSSI"
Pour plus d'informations, voir perlobj (pour tous les petits de\*'tails au
sujet des objets Perl, maintenant que vous avez vu les bases), perltoot (le
tutoriel pour ceux qui connaissent de\*'ja\*` les objets, la page de manuel
perltooc (qui traite les classes de donne\*'es), perlbot (pour les trucs
et astuces), et des livres tels que l'excellent \fIObject Oriented Perl\fR de
Damian Conway.
.PP
Citons quelques modules qui sont digne d'inte\*'re\*^t Class::Accessor,
Class::Class, Class::Contract, Class::Data::Inheritable, Class::MethodMaker et
Tie::SecureHash
.SH "COPYRIGHT"
.IX Header "COPYRIGHT"
Copyright (c) 1999, 2000 by Randal L. Schwartz and Stonehenge Consulting
Services, Inc. Permission is hereby granted to distribute this document
intact with the Perl distribution, and in accordance with the licenses of the
Perl distribution; derived documents must include this copyright notice
intact.
.PP
Portions of this text have been derived from Perl Training materials
originally appearing in the \fIPackages, References, Objects, and
Modules\fR course taught by instructors for Stonehenge Consulting
Services, Inc. and used with permission.
.PP
Portions of this text have been derived from materials originally
appearing in \fILinux Magazine\fR and used with permission.
.SH "TRADUCTION"
.IX Header "TRADUCTION"
.Sh "Version"
.IX Subsection "Version"
Cette traduction franc\*,aise correspond a\*` la version anglaise distribue\*'e avec
perl 5.8.8. Pour en savoir plus concernant ces traductions, consultez
.
.Sh "Traducteur"
.IX Subsection "Traducteur"
Paul Gaborit avec la participation de Ge\*'rard Robin
.
.Sh "Relecture"
.IX Subsection "Relecture"
Jean Forget . Ge\*'rard Delafond.