Il s'agit de la commande perlobj qui peut être exécutée dans le fournisseur d'hébergement gratuit OnWorks en utilisant l'un de nos nombreux postes de travail en ligne gratuits tels que Ubuntu Online, Fedora Online, l'émulateur en ligne Windows ou l'émulateur en ligne MAC OS
PROGRAMME:
Nom
perlobj - Référence d'objet Perl
DESCRIPTION
Ce document fournit une référence sur les fonctionnalités d'orientation objet de Perl. Si vous êtes
à la recherche d'une introduction à la programmation orientée objet en Perl, veuillez consulter perlootut.
Pour comprendre les objets Perl, vous devez d'abord comprendre les références en Perl. Voir
perlref pour plus de détails.
Ce document décrit toutes les fonctionnalités orientées objet (OO) de Perl, de A à Z. Si
vous cherchez simplement à écrire votre propre code orienté objet, vous êtes probablement
il est préférable d'utiliser l'un des systèmes d'objets du CPAN décrits dans perlootut.
Si vous cherchez à écrire votre propre système d'objets ou si vous devez maintenir du code qui
implémente des objets à partir de zéro, alors ce document vous aidera à comprendre exactement comment
Perl fait de l'orientation objet.
Il existe quelques principes de base qui définissent Perl orienté objet :
1. Un objet est simplement une structure de données qui sait à quelle classe il appartient.
2. Une classe est simplement un package. Elle fournit des méthodes qui s'attendent à fonctionner sur
objets.
3. Une méthode est simplement une sous-routine qui attend une référence à un objet (ou un package)
nom, pour les méthodes de classe) comme premier argument.
Examinons chacun de ces principes en profondeur.
An Exlcusion is Vous n’avez qu’à vous a Date Structure
Contrairement à de nombreux autres langages qui prennent en charge l’orientation objet, Perl ne fournit aucune
Syntaxe spéciale pour la construction d'un objet. Les objets ne sont que des structures de données Perl.
(hachages, tableaux, scalaires, handles de fichiers, etc.) qui ont été explicitement associés à un
classe particulière.
Cette association explicite est créée par la fonction intégrée « bless », qui est généralement
utilisé au sein de la constructeur sous-routine de la classe.
Voici un constructeur simple :
Fichier de package ;
sous nouveau {
ma $classe = shift;
return béni {}, $classe ;
}
Le nom « nouveau » n'a rien de spécial. Nous pourrions nommer notre constructeur autrement :
Fichier de package ;
sous-charge {
ma $classe = shift;
return béni {}, $classe ;
}
La convention moderne pour les modules OO est de toujours utiliser « nouveau » comme nom pour le
constructeur, mais il n'y a aucune obligation de le faire. Toute sous-routine qui valide une donnée
La structure dans une classe est un constructeur valide en Perl.
Dans les exemples précédents, le code « {} » crée une référence à un hachage anonyme vide.
La fonction « bless » prend ensuite cette référence et associe le hachage à la classe dans
$class. Dans le cas le plus simple, la variable $class contiendra la chaîne
"Déposer".
Nous pouvons également utiliser une variable pour stocker une référence à la structure de données en cours
béni comme notre objet :
sous nouveau {
ma $classe = shift;
mon $self = {};
bénissez $self, $class ;
renvoie $self ;
}
Une fois que nous avons validé le hachage référencé par $self, nous pouvons commencer à appeler des méthodes dessus.
est utile si vous souhaitez placer l'initialisation de l'objet dans sa propre méthode distincte :
sous nouveau {
ma $classe = shift;
mon $self = {};
bénissez $self, $class ;
$self->_initialize();
renvoie $self ;
}
Étant donné que l'objet est également un hachage, vous pouvez le traiter comme tel et l'utiliser pour stocker des données.
associé à l'objet. En général, le code de la classe peut traiter le hachage comme un
structure de données accessible, tandis que le code extérieur à la classe doit toujours traiter l'objet comme
opaque. C'est ce qu'on appelle encapsulation. L'encapsulation signifie que l'utilisateur d'un objet ne
Il n'est pas nécessaire de savoir comment l'implémentation est effectuée. L'utilisateur appelle simplement les méthodes documentées sur le
objet.
Notez cependant que (contrairement à la plupart des autres langages OO) Perl ne garantit ni n'applique
encapsulation de quelque manière que ce soit. Si vous souhaitez que les objets be opaque, vous devez organiser
Vous pouvez le faire vous-même. Cela peut se faire de différentes manières, notamment en utilisant « Inside-Out ».
objets" ou modules du CPAN.
Objets Emplacements Béni; Variables Emplacements Pas
Lorsque nous bénissons quelque chose, nous ne bénissons pas la variable qui contient une référence à
cette chose, et nous ne bénissons pas non plus la référence que la variable stocke ; nous bénissons
la chose à laquelle la variable fait référence (parfois appelée référent). C'est le meilleur
démontré avec ce code :
utilisez Scalar::Util 'béni';
mon $foo = {};
mon $bar = $foo;
bénis $foo, 'Classe';
print blessed( $bar ) // 'non béni'; # imprime "Classe"
$bar = "une autre valeur";
print blessed( $bar ) // 'non béni'; # imprime "non béni"
Lorsque nous appelons « bless » sur une variable, nous bénissons en fait la structure de données sous-jacente
à laquelle la variable fait référence. Nous ne bénissons ni la référence elle-même, ni la variable
qui contient cette référence. C'est pourquoi le deuxième appel à « blessed( $bar ) » renvoie
faux. À ce stade, $bar ne stocke plus de référence à un objet.
Vous verrez parfois des livres ou des documents plus anciens mentionner « bénir une référence » ou
Décrire un objet comme une « référence bénie » est incorrect. Il ne s'agit pas de la référence.
qui est béni en tant qu'objet ; c'est la chose à laquelle la référence fait référence (c'est-à-dire le référent).
A Classe is Vous n’avez qu’à vous a Forfait
Perl ne fournit aucune syntaxe particulière pour les définitions de classes. Un paquet est simplement un
Espace de noms contenant des variables et des sous-routines. La seule différence est que, dans une classe,
les sous-routines peuvent s'attendre à une référence à un objet ou au nom d'une classe comme premier
argument. Ceci est purement une question de convention, donc une classe peut contenir à la fois des méthodes et
sous-routines qui ne le font pas opérer sur un objet ou une classe.
Chaque paquet contient un tableau spécial appelé @ISA. Ce tableau contient une liste de ces
les classes parentes de la classe, le cas échéant. Ce tableau est examiné lors de la résolution des méthodes par Perl.
que nous aborderons plus tard.
Il est possible de définir manuellement @ISA, et vous pouvez le constater dans du code Perl plus ancien.
Le code utilise également le pragma de base. Pour le nouveau code, nous recommandons d'utiliser le pragma parent.
pour déclarer vos parents. Ce pragma se chargera de configurer @ISA. Il chargera également
les classes parentes et assurez-vous que le package n'hérite pas de lui-même.
Quelle que soit la manière dont les classes parentes sont définies, la variable @ISA du package contiendra une liste de
ces parents. Il s'agit simplement d'une liste de scalaires, chacun étant une chaîne de caractères
correspond à un nom de package.
Toutes les classes héritent implicitement de la classe UNIVERSAL. La classe UNIVERSAL est
implémenté par le noyau Perl, et fournit plusieurs méthodes par défaut, telles que « isa() »,
« can() » et « VERSION() ». La classe « UNIVERSAL » jamais apparaître dans l'@ISA d'un package
variable.
Perl uniquement fournit l'héritage de méthode comme fonctionnalité intégrée. L'héritage d'attribut est
Il reste à la classe d'implémenter. Voir la section « Écriture d'accesseurs » pour plus de détails.
A Méthode is Vous n’avez qu’à vous a Sous-programme
Perl ne fournit aucune syntaxe particulière pour définir une méthode. Une méthode est simplement un
sous-routine régulière, et est déclarée avec « sub ». Ce qui rend une méthode spéciale, c'est qu'elle
s'attend à recevoir soit un objet, soit un nom de classe comme premier argument.
Perl ne fournit une syntaxe spéciale pour l'invocation de méthode, l'opérateur « -> ». Nous aborderons
cela plus en détail plus tard.
La plupart des méthodes que vous écrivez s'attendent à fonctionner sur des objets :
sous-enregistrer {
mon $self = shift;
ouvre mon $fh, '>', $self->path() ou meurs $!;
imprimez {$fh} $self->data() ou mourrez $!;
ferme $fh ou meurs $!;
}
Méthode Invocation
L'appel d'une méthode sur un objet s'écrit "$object->method".
Le côté gauche de l'opérateur d'invocation de méthode (ou flèche) est l'objet (ou la classe)
nom), et le côté droit est le nom de la méthode.
mon $pod = Fichier->nouveau( 'perlobj.pod', $data );
$pod->save();
La syntaxe « -> » est également utilisée pour déréférencer une référence. Elle ressemble à ceci :
opérateur, mais ce sont deux opérations différentes.
Lorsque vous appelez une méthode, l'élément situé à gauche de la flèche est transmis en premier.
argument de la méthode. Cela signifie que lorsque nous appelons « Critter->new() », la méthode « new() »
reçoit la chaîne « Critter » comme premier argument. Lorsque nous appelons « $fred->speak() »,
La variable $fred est passée comme premier argument à « speak() ».
Comme avec n'importe quelle sous-routine Perl, tous les arguments passés dans @_ sont des alias du
argument original. Cela inclut l'objet lui-même. Si vous l'affectez directement à $_[0],
modifiera le contenu de la variable contenant la référence à l'objet. Nous
Je vous recommande de ne pas faire cela à moins que vous ne sachiez exactement ce que vous faites.
Perl sait dans quel paquet se trouve la méthode en regardant le côté gauche de la flèche. Si
Le côté gauche est un nom de package, et la méthode est recherchée dans ce package. Si le côté gauche
côté main est un objet, alors Perl recherche la méthode dans le package que l'objet a
été béni.
Si le côté gauche n'est ni un nom de package ni un objet, alors l'appel de méthode sera
provoquer une erreur, mais consultez la section sur les « Variations d'appel de méthode » pour plus de nuances.
Droit des successions
Nous avons déjà parlé du tableau spécial @ISA et du pragma parent.
Lorsqu'une classe hérite d'une autre classe, toutes les méthodes définies dans la classe parent sont
disponible pour la classe enfant. Si vous tentez d'appeler une méthode sur un objet qui n'est pas
définie dans sa propre classe, Perl recherchera également cette méthode dans toutes les classes parentes qu'il peut
avoir.
Fichier de paquet::MP3;
utiliser le parent 'Fichier'; # définit @File::MP3::ISA = ('Fichier');
mon $mp3 = Fichier::MP3->nouveau( 'Andvari.mp3', $data );
$mp3->enregistrer();
Comme nous n'avons pas défini de méthode « save() » dans la classe « File::MP3 », Perl examinera le
Les classes parentes de la classe « File::MP3 » pour trouver la méthode « save() ». Si Perl ne trouve pas de
Si vous supprimez la méthode « save() » n'importe où dans la hiérarchie d'héritage, elle mourra.
Dans ce cas, la méthode « save() » est trouvée dans la classe « File ». Notez que l'objet transmis
"save()" dans ce cas est toujours un objet "File::MP3", même si la méthode se trouve dans
la classe "Fichier".
Nous pouvons surcharger la méthode d'un parent dans une classe enfant. Ce faisant, nous pouvons toujours appeler la méthode.
méthode de la classe parente avec la pseudo-classe « SUPER ».
sous-enregistrer {
mon $self = shift;
dites « Préparez-vous à bouger » ;
$self->SUPER::save();
}
Le modificateur « SUPER » peut uniquement être utilisé pour les appels de méthodes. Vous ne pouvez pas l'utiliser pour des appels classiques.
appels de sous-routines ou méthodes de classe :
SUPER::save($thing); # FAIL : recherche le sous-programme save() dans le package SUPER
SUPER->save($thing); # FAIL : recherche la méthode save() dans la classe
# SUPER
$thing->SUPER::save(); # Ok : recherche la méthode save() dans le parent
# classes
Comment la SUPER is Résolu
La pseudo-classe « SUPER » est résolue à partir du package où l'appel est effectué. Elle est pas
résolu en fonction de la classe de l'objet. Ceci est important, car cela permet aux méthodes de
différents niveaux au sein d'une hiérarchie d'héritage profonde, chacun appelle correctement son
méthodes parentes.
paquet A;
sous nouveau {
retourner blesser {}, shift;
}
sous-parler {
mon $self = shift;
dis « A » ;
}
paquet B;
utiliser le parent -norequire, 'A';
sous-parler {
mon $self = shift;
$self->SUPER::speak();
dis « B » ;
}
paquet C;
utiliser le parent -norequire, 'B';
sous-parler {
mon $self = shift;
$self->SUPER::speak();
dis « C » ;
}
mon $c = C->nouveau();
$c->parler();
Dans cet exemple, nous obtiendrons le résultat suivant :
A
B
C
Ceci illustre la résolution de « SUPER ». Même si l'objet est béni dans le « C »,
classe, la méthode "speak()" dans la classe "B" peut toujours appeler "SUPER::speak()" et s'attendre à ce qu'elle
pour rechercher correctement dans la classe parente de « B » (c'est-à-dire la classe dans laquelle se trouve l'appel de méthode), et non dans
la classe parente de « C » (c'est-à-dire la classe à laquelle appartient l'objet).
Il existe de rares cas où cette résolution basée sur un package peut poser problème. Si vous copiez un
sous-routine d'un package à un autre, la résolution « SUPER » sera effectuée en fonction de la
emballage d'origine.
Multiple Droit des successions
L'héritage multiple indique souvent un problème de conception, mais Perl vous en donne toujours suffisamment.
une corde pour te pendre si tu le demandes.
Pour déclarer plusieurs parents, il vous suffit de passer plusieurs noms de classe à « use parent » :
paquet MultiChild;
utiliser le parent 'Parent1', 'Parent2';
Méthode Résolution Order
L'ordre de résolution des méthodes n'a d'importance qu'en cas d'héritage multiple. Dans ce cas,
héritage unique, Perl recherche simplement la chaîne d'héritage pour trouver une méthode :
Grand-parent
|
Parent
|
Enfant
Si nous appelons une méthode sur un objet « Enfant » et que cette méthode n'est pas définie dans l'objet « Enfant »
classe, Perl recherchera cette méthode dans la classe « Parent » puis, si nécessaire, dans la
Classe « Grand-parent ».
Si Perl ne trouve pas la méthode dans aucune de ces classes, il s'arrêtera avec un message d'erreur.
Lorsqu'une classe a plusieurs parents, l'ordre de recherche des méthodes devient plus compliqué.
Par défaut, Perl effectue une recherche en profondeur, de gauche à droite, pour une méthode. Cela signifie qu'elle
commence par le premier parent dans le tableau @ISA, puis recherche tous ses parents,
grands-parents, etc. S'il ne parvient pas à trouver la méthode, il passe alors au parent suivant dans le
tableau @ISA de la classe d'origine et recherche à partir de là.
Arrière-grand-parent partagé
/ \
Grand-parent paternelGrand-parent maternel
\ /
Père Mère
\ /
Enfant
Ainsi, étant donné le diagramme ci-dessus, Perl recherchera « Enfant », « Père », « Grand-parent paternel »,
« Arrière-grand-parent commun », « Mère » et enfin « Grand-parent maternel ». Il peut s'agir d'un
problème car maintenant nous cherchons dans « SharedBackGrandParent » avant nous avons vérifié tous ses
classes dérivées (c'est-à-dire avant d'essayer « Mother » et « MaternalGrandparent »).
Il est possible de demander un ordre de résolution de méthode différent avec le pragma mro.
paquet Enfant;
utiliser mro 'c3';
utiliser le parent « Père », « Mère » ;
Ce pragma permet de passer à l'ordre de résolution « C3 ». En termes simples, l'ordre « C3 »
garantit que les classes parentes partagées ne sont jamais recherchées avant les classes enfants, donc Perl va
recherchez maintenant : « Enfant », « Père », « Grand-parent paternel », « Mère », « Grand-parent maternel », et
Enfin, « Arrière-Grand-Parent Partagé ». Notez toutefois qu'il ne s'agit pas d'une recherche en largeur :
Tous les ancêtres « Père » (à l'exception de l'ancêtre commun) sont recherchés avant l'un des
Les ancêtres « maternels » sont pris en compte.
L'ordre C3 vous permet également d'appeler des méthodes dans des classes sœurs avec la pseudo-classe « next ».
Consultez la documentation mro pour plus de détails sur cette fonctionnalité.
Méthode Résolution Cache haute performance
Lorsque Perl recherche une méthode, il met en cache la recherche afin que les futurs appels à la méthode
Il n'est pas nécessaire de le rechercher à nouveau. Modifier la classe parente d'une classe ou ajouter des sous-routines
à une classe invalidera le cache de cette classe.
Le pragma mro fournit certaines fonctions permettant de manipuler directement le cache de méthodes.
Écriture Constructeurs
Comme mentionné précédemment, Perl ne fournit aucune syntaxe de constructeur particulière. Cela signifie qu'un
Chaque classe doit implémenter son propre constructeur. Un constructeur est simplement une méthode de classe qui
renvoie une référence à un nouvel objet.
Le constructeur peut également accepter des paramètres supplémentaires définissant l'objet. Écrivons
un vrai constructeur pour la classe "File" que nous avons utilisée précédemment :
Fichier de package ;
sous nouveau {
ma $classe = shift;
mon ( $chemin, $données ) = @_;
mon $moi = bénir {
chemin => $chemin,
données => $données,
}, $classe ;
renvoie $self ;
}
Comme vous pouvez le constater, nous avons stocké le chemin d'accès et les données du fichier dans l'objet lui-même. N'oubliez pas que sous
Le capot, cet objet n'est encore qu'un hachage. Plus tard, nous écrirons des accesseurs pour manipuler
ces données.
Pour notre classe File::MP3, nous pouvons vérifier que le chemin qui nous est donné se termine par
".mp3":
Fichier de paquet::MP3;
sous nouveau {
ma $classe = shift;
mon ( $chemin, $données ) = @_;
"Vous ne pouvez pas créer un fichier::MP3 sans extension mp3\n"
sauf si $path =~ /\.mp3\z/;
retourner $class->SUPER::new(@_);
}
Ce constructeur permet à sa classe parente d'effectuer la construction réelle de l'objet.
Attributs
Un attribut est une donnée appartenant à un objet particulier. Contrairement à la plupart des attributs d'objet,
langages orientés, Perl ne fournit aucune syntaxe ou support spécial pour déclarer et
manipulation des attributs.
Les attributs sont souvent stockés dans l'objet lui-même. Par exemple, si l'objet est un
hachage anonyme, nous pouvons stocker les valeurs d'attribut dans le hachage en utilisant le nom de l'attribut comme
la clé.
Bien qu'il soit possible de faire référence directement à ces clés de hachage en dehors de la classe, il est
il est considéré comme une bonne pratique d'encapsuler tout accès à l'attribut avec des méthodes d'accès.
Cela présente plusieurs avantages. Les accesseurs facilitent la modification de l'implémentation d'un
objet plus tard tout en préservant l'API d'origine.
Un accesseur vous permet d'ajouter du code supplémentaire pour l'accès aux attributs. Par exemple, vous pourriez
appliquer une valeur par défaut à un attribut qui n'a pas été défini dans le constructeur, ou vous pouvez valider
qu'une nouvelle valeur pour l'attribut est acceptable.
Enfin, l'utilisation d'accesseurs simplifie grandement l'héritage. Les sous-classes peuvent utiliser ces accesseurs.
plutôt que de devoir savoir comment une classe parent est implémentée en interne.
Écriture Accesseurs
Comme pour les constructeurs, Perl ne fournit aucune syntaxe de déclaration d'accesseur spéciale, donc les classes
doivent fournir des méthodes d'accès explicitement écrites. Il existe deux types courants de
accesseurs, lecture seule et lecture-écriture.
Un simple accesseur en lecture seule obtient simplement la valeur d'un seul attribut :
sous-chemin {
mon $self = shift;
retourner $self->{chemin};
}
Un accesseur en lecture-écriture permettra à l'appelant de définir la valeur ainsi que de l'obtenir :
sous-chemin {
mon $self = shift;
si (@_) {
$self->{path} = décalage ;
}
retourner $self->{chemin};
}
An Au-delà À propos Smarter et Plus sûr Code
Notre constructeur et nos accesseurs ne sont pas très intelligents. Ils ne vérifient pas qu'un $path est
défini, et ils ne vérifient pas non plus qu'un $path est un chemin de système de fichiers valide.
Effectuer ces vérifications à la main peut vite devenir fastidieux. Écrire une multitude d'accesseurs par
La manipulation manuelle est également extrêmement fastidieuse. De nombreux modules sur CPAN peuvent vous aider.
écrivez du code plus sûr et plus concis, y compris les modules que nous recommandons dans perlootut.
Méthode Appeler Variations
Perl prend en charge plusieurs autres façons d'appeler des méthodes en plus de l'utilisation de « $object->method() »
nous avons vu jusqu'à présent.
Méthode Des noms as String
Perl vous permet d'utiliser une variable scalaire contenant une chaîne comme nom de méthode :
mon $fichier = Fichier->nouveau( $chemin, $données );
ma $méthode = 'enregistrer';
$fichier->$méthode();
Cela fonctionne exactement comme l'appel de « $file->save() ». Cela peut être très utile pour écrire.
Code dynamique. Par exemple, il permet de passer le nom d'une méthode à appeler en paramètre.
à une autre méthode.
Classe Des noms as String
Perl vous permet également d'utiliser un scalaire contenant une chaîne comme nom de classe :
ma $class = 'Fichier';
mon $fichier = $classe->nouveau( $chemin, $données );
Encore une fois, cela permet un code très dynamique.
Sous-programme Références as Méthodologie
Vous pouvez également utiliser une référence de sous-routine comme méthode :
mon $sub = sub {
mon $self = shift;
$self->save();
};
$fichier->$sub();
Cela équivaut exactement à écrire « $sub->($file) ». Vous pouvez rencontrer cette expression dans la nature.
combiné avec un appel à « can » :
si ( mon $meth = $object->can('foo') ) {
$objet->$meth();
}
Déférencement Méthode Appeler
Perl permet également d'utiliser une référence scalaire déréférencée dans un appel de méthode. C'est
une bouchée, alors regardons un peu de code :
$file->${ \'save' };
$file->${ returns_scalar_ref() };
$file->${ \( returns_scalar() ) };
$file->${ renvoie_ref_à_sous_ref() };
Cela fonctionne si la déréférence produit une chaîne or une référence de sous-routine.
Méthode Appels on Descripteurs de fichiers
Sous le capot, les handles de fichiers Perl sont des instances de la classe « IO::Handle » ou « IO::File ».
Une fois un handle de fichier ouvert, vous pouvez appeler des méthodes dessus. De plus, vous pouvez appeler
méthodes sur les handles de fichiers « STDIN », « STDOUT » et « STDERR ».
ouvre mon $fh, '>', 'chemin/vers/fichier';
$fh->autoflush();
$fh->print('contenu');
STDOUT->autoflush();
Invoquer Classe Méthodologie
Étant donné que Perl vous permet d'utiliser des mots nus pour les noms de paquets et les noms de sous-routines, il
interprète parfois incorrectement le sens d'un mot nu. Par exemple, la construction
« Classe->nouveau() » peut être interprété comme « 'Classe'->nouveau() » ou « Classe()->nouveau() ».
En anglais, cette deuxième interprétation se lit comme « appeler une sous-routine nommée Classe(), puis appelez
Nouveau() en tant que méthode sur la valeur de retour de Classe()". S'il existe une sous-routine nommée
"Class()" dans l'espace de noms actuel, Perl interprétera toujours "Class->new()" comme
deuxième alternative : un appel à « new() » sur l'objet renvoyé par un appel à « Class() »
Vous pouvez forcer Perl à utiliser la première interprétation (c'est-à-dire comme un appel de méthode sur la classe)
nommée « Classe ») de deux manières. Premièrement, vous pouvez ajouter un « :: » au nom de la classe :
Classe::->new()
Perl interprétera toujours cela comme un appel de méthode.
Alternativement, vous pouvez citer le nom de la classe :
'Classe' -> nouveau()
Bien sûr, si le nom de la classe est dans un scalaire, Perl fera également ce qu'il faut :
ma $classe = 'Classe';
$class->nouveau();
Indirect Exlcusion Syntaxe
extérieur of le filet manipuler Cas, utilisé of ceci. syntaxe is découragé as it Vous pouvez embrouiller le
Perl interprète. See ci-dessous pour plus détails.
Perl prend en charge une autre syntaxe d'invocation de méthode appelée notation « objet indirect ».
la syntaxe est dite « indirecte » car la méthode précède l'objet pour lequel elle est invoquée
sur.
Cette syntaxe peut être utilisée avec n'importe quelle méthode de classe ou d'objet :
mon $file = nouveau fichier $path, $data;
enregistrer $file;
Nous vous recommandons d’éviter cette syntaxe, pour plusieurs raisons.
Premièrement, la lecture peut être complexe. Dans l'exemple ci-dessus, il n'est pas clair si « enregistrer » est un
méthode fournie par la classe « Fichier » ou simplement une sous-routine qui attend un objet fichier comme
son premier argument.
Utilisé avec des méthodes de classe, le problème est encore plus grave. Perl autorise les sous-routines.
les noms doivent être écrits sous forme de mots nus, Perl doit deviner si le mot nu après la méthode
est un nom de classe ou de sous-routine. Autrement dit, Perl peut résoudre la syntaxe comme suit :
"Fichier->nouveau( $chemin, $données )" or "nouveau( Fichier( $chemin, $données ) )".
Pour analyser ce code, Perl utilise une heuristique basée sur les noms de paquets qu'il a vus, ce qu'il
les sous-routines existent dans le package actuel, les mots-clés qu'il a vus précédemment et d'autres
entrée. Inutile de dire que les heuristiques peuvent produire des résultats très surprenants !
La documentation plus ancienne (et certains modules CPAN) encourageaient cette syntaxe, en particulier pour
constructeurs, vous pourriez donc encore le trouver dans la nature. Cependant, nous vous encourageons à l'éviter.
l'utiliser dans un nouveau code.
Vous pouvez forcer Perl à interpréter le mot nu comme un nom de classe en y ajoutant « :: », comme
nous avons vu plus tôt :
mon $fichier = nouveau Fichier:: $chemin, $données;
"bénir", "béni", et "réf"
Comme nous l’avons vu précédemment, un objet est simplement une structure de données qui a été intégrée dans une classe
via la fonction « bless ». Cette fonction peut accepter un ou deux arguments :
mon $objet = bless {}, $class;
mon $objet = bless {};
Dans la première forme, le hachage anonyme est ajouté à la classe $class. Dans la
deuxième forme, le hachage anonyme est béni dans le package actuel.
La deuxième forme est fortement déconseillée, car elle brise la capacité d'une sous-classe à
réutilisez le constructeur du parent, mais vous pouvez toujours le rencontrer dans le code existant.
Si vous souhaitez savoir si un scalaire particulier fait référence à un objet, vous pouvez utiliser le
Fonction « blessed » exportée par Scalar::Util, qui est fournie avec le noyau Perl.
utilisez Scalar::Util 'béni';
si ( défini béni($chose) ) { ... }
Si $thing fait référence à un objet, alors cette fonction renvoie le nom du package
L'objet a été béni. Si $thing ne contient pas de référence à un objet béni,
la fonction "blessed" renvoie "undef".
Notez que « blessed($thing) » renverra également false si $thing a été béni dans une classe
Nommée « 0 ». C'est possible, mais assez pathologique. Ne créez pas de classe nommée « 0 ».
à moins que tu saches ce que tu fais.
De même, la fonction « ref » intégrée de Perl traite une référence à un objet béni
spécialement. Si vous appelez « ref($thing) » et que $thing contient une référence à un objet, il
renvoie le nom de la classe dans laquelle l'objet a été béni.
Si vous souhaitez simplement vérifier qu'une variable contient une référence d'objet, nous vous recommandons
que vous utilisez « defined blessed($object) », puisque « ref » renvoie des valeurs vraies pour tous
des références, pas seulement des objets.
Le manuel de formation UNIVERSEL Classe
Toutes les classes héritent automatiquement de la classe UNIVERSAL, qui est intégrée à Perl
noyau. Cette classe fournit un certain nombre de méthodes, qui peuvent toutes être appelées sur un
classe ou un objet. Vous pouvez également choisir de surcharger certaines de ces méthodes dans votre classe.
Si vous le faites, nous vous recommandons de suivre la sémantique intégrée décrite ci-dessous.
isa($classe)
La méthode « isa » renvoie oui si l'objet est un membre de la classe dans $class, ou un
membre d'une sous-classe de $class.
Si vous remplacez cette méthode, elle ne devrait jamais générer d’exception.
FAIT($rôle)
La méthode « DOES » renvoie oui si son objet prétend jouer le rôle $role.
Par défaut, cette méthode est équivalente à « isa ». Cette méthode est destinée aux systèmes d'objets.
extensions qui implémentent des rôles, comme « Moose » et « Role::Tiny ».
Vous pouvez également surcharger « DOES » directement dans vos classes. Si vous surchargez ceci
méthode, elle ne devrait jamais générer d'exception.
peut($méthode)
La méthode « can » vérifie si la classe ou l'objet sur lequel elle a été appelée possède une méthode
nommée $method. Cette méthode est vérifiée dans la classe et dans tous ses parents. Si
Si la méthode existe, une référence à la sous-routine est renvoyée. Si ce n'est pas le cas,
"undef" est renvoyé.
Si votre classe répond aux appels de méthode via « AUTOLOAD », vous souhaiterez peut-être surcharger « can »
pour renvoyer une référence de sous-routine pour les méthodes gérées par votre méthode « AUTOLOAD ».
Si vous remplacez cette méthode, elle ne devrait jamais générer d’exception.
VERSION($need)
La méthode « VERSION » renvoie le numéro de version de la classe (package).
Si l'argument $need est donné, il vérifiera que la version actuelle (telle que définie
par la variable $VERSION dans le package) est supérieur ou égal à $need ; il sera
Si ce n'est pas le cas, la méthode est automatiquement appelée par le formulaire « VERSION ».
de « l'utilisation ».
utiliser le package 1.2 qw (certains sous-marins importés) ;
# implique :
Paquet->VERSION(1.2);
Nous vous recommandons d'utiliser cette méthode pour accéder à la version d'un autre package, plutôt que
en regardant directement $Package::VERSION. Le paquet que vous consultez pourrait avoir
a remplacé la méthode « VERSION ».
Nous recommandons également d'utiliser cette méthode pour vérifier si un module dispose d'un
version. L'implémentation interne utilise le module de version pour s'assurer que
les différents types de numéros de version sont comparés correctement.
CHARGEMENT AUTOMATIQUE
Si vous appelez une méthode qui n'existe pas dans une classe, Perl génèrera une erreur. Cependant, si
cette classe ou l'une de ses classes parentes définit une méthode « AUTOLOAD », cette « AUTOLOAD »
la méthode est appelée à la place.
« AUTOLOAD » est appelé comme une méthode régulière et l'appelant ne connaîtra pas la différence.
Quelle que soit la valeur renvoyée par votre méthode « AUTOLOAD », elle est renvoyée à l'appelant.
Le nom de la méthode entièrement qualifiée qui a été appelée est disponible dans le package $AUTOLOAD
global pour votre classe. Puisqu'il s'agit d'un global, si vous souhaitez y faire référence, faites-le sans
préfixe de nom de package sous « strict 'vars' », vous devez le déclarer.
# XXX - c'est une façon terrible d'implémenter des accesseurs, mais cela rend
# pour un exemple simple.
notre $AUTOLOAD;
sous-CHARGEMENT AUTOMATIQUE {
mon $self = shift;
# Supprimer le qualificatif du nom de la méthode d'origine...
mon $appelé = $AUTOLOAD =~ s/.*:://r;
# Existe-t-il un attribut de ce nom ?
die "Aucun attribut de ce type : $called"
à moins qu'il existe $self->{$called};
# Si c'est le cas, retournez-le...
retourner $self->{$appelé};
}
sous DESTROY { } # voir ci-dessous
Sans la déclaration « our $AUTOLOAD », ce code ne sera pas compilé sous les conditions strictes
pragmatique.
Comme le dit le commentaire, ce n'est pas une bonne façon d'implémenter des accesseurs. C'est lent et trop
C'est très astucieux. Cependant, vous pourriez y voir un moyen de fournir des accesseurs dans du code Perl plus ancien.
Voir perlootut pour des recommandations sur le codage OO en Perl.
Si votre classe possède une méthode « AUTOLOAD », nous vous recommandons fortement de la remplacer
« can » dans votre classe également. Votre méthode « can » surchargée devrait renvoyer une sous-routine.
référence pour toute méthode à laquelle votre « AUTOLOAD » répond.
Destructeurs
Lorsque la dernière référence à un objet disparaît, l'objet est détruit. Si vous n'avez que
une référence à un objet stocké dans un scalaire lexical, l'objet est détruit lorsque cela
scalaire est hors de portée. Si vous stockez l'objet dans un package global, il se peut que cet objet ne soit pas
sortir du champ d'application jusqu'à ce que le programme se termine.
Si vous souhaitez faire quelque chose lorsque l'objet est détruit, vous pouvez définir une opération « DÉTRUIRE »
méthode dans votre classe. Cette méthode sera toujours appelée par Perl au moment opportun,
sauf si la méthode est vide.
Cette méthode s'appelle comme n'importe quelle autre méthode, avec l'objet comme premier argument.
ne reçoit aucun argument supplémentaire. Cependant, la variable $_[0] sera en lecture seule dans le
destructeur, vous ne pouvez donc pas lui attribuer de valeur.
Si votre méthode « DESTROY » génère une erreur, celle-ci sera ignorée. Elle ne sera pas envoyée.
sur « STDERR » et cela n'entraînera pas l'arrêt du programme. Cependant, si votre destructeur est
exécuté à l'intérieur d'un bloc "eval {}", l'erreur modifiera la valeur de $@.
Étant donné que les méthodes « DESTROY » peuvent être appelées à tout moment, vous devez localiser toutes les méthodes globales.
variables que vous pourriez mettre à jour dans votre commande « DESTROY ». En particulier, si vous utilisez « eval {} »,
devrait localiser $@, et si vous utilisez « system » ou des backticks, vous devriez localiser $?.
Si vous définissez un « AUTOLOAD » dans votre classe, alors Perl appellera votre « AUTOLOAD » pour gérer
la méthode « DESTROY ». Vous pouvez éviter cela en définissant une valeur « DESTROY » vide, comme nous l'avons fait dans
l'exemple de chargement automatique. Vous pouvez également vérifier la valeur de $AUTOLOAD et la renvoyer sans
faire quoi que ce soit lorsqu'on lui demande de gérer « DÉTRUIRE ».
Global Destruction
L'ordre dans lequel les objets sont détruits lors de la destruction globale avant le programme
Les sorties sont imprévisibles. Cela signifie que les objets contenus dans votre objet peuvent déjà
ont été détruits. Vous devez vérifier qu'un objet contenu est défini avant d'appeler une
méthode dessus :
sous-DÉTRUIRE {
mon $self = shift;
$self->{handle}->close() si $self->{handle};
}
Vous pouvez utiliser la variable « ${^GLOBAL_PHASE} » pour détecter si vous êtes actuellement dans le global
phase de destruction :
sous-DÉTRUIRE {
mon $self = shift;
retourner si ${^GLOBAL_PHASE} eq 'DESTRUCT';
$self->{handle}->close();
}
Notez que cette variable a été ajoutée dans Perl 5.14.0. Si vous souhaitez détecter la variable globale
phase de destruction sur les anciennes versions de Perl, vous pouvez utiliser « Devel::GlobalDestruction »
module sur CPAN.
Si votre méthode « DESTROY » émet un avertissement lors de la destruction globale, l'interpréteur Perl
ajoutera la chaîne « pendant la destruction globale » à l'avertissement.
Lors de la destruction globale, Perl effectuera toujours un ramasse-miettes des objets avant qu'ils ne soient non bénis
Références. Voir « PERL_DESTRUCT_LEVEL » dans perlhacktips pour plus d'informations sur les références globales.
destruction.
Non-hachage Objets
Jusqu'à présent, tous les exemples ont montré des objets basés sur un hachage béni. Cependant,
possible de bénir tout type de structure de données ou de référent, y compris les scalaires, les globs et
sous-routines. Vous pouvez rencontrer ce genre de choses en observant du code.
Voici un exemple de module en tant que scalaire béni :
paquet Heure;
utiliser strict;
utiliser des avertissements ;
sous nouveau {
ma $classe = shift;
mon $temps = temps;
return bénit \$time, $class;
}
sous-époque {
mon $self = shift;
retourner ${ $self };
}
mon $time = Time->new();
imprimer $time->epoch();
Inside-Out objets
Dans le passé, la communauté Perl a expérimenté une technique appelée « objets à l'envers ».
Un objet inversé stocke ses données en dehors de la référence de l'objet, indexées sur un
propriété unique de l'objet, telle que son adresse mémoire, plutôt que dans l'objet
lui-même. Cela présente l'avantage de renforcer l'encapsulation des attributs d'objet, car
leurs données ne sont pas stockées dans l'objet lui-même.
Cette technique était populaire pendant un certain temps (et était recommandée dans le livre de Damian Conway). Perl Mieux
Expertises), mais n'a jamais été universellement adopté. Le module Object::InsideOut sur CPAN
fournit une implémentation complète de cette technique, et vous pouvez la voir ou d'autres
modules à l'envers dans la nature.
Voici un exemple simple de la technique, utilisant le module de base Hash::Util::FieldHash.
Ce module a été ajouté au noyau pour prendre en charge les implémentations d'objets de l'intérieur vers l'extérieur.
paquet Heure;
utiliser strict;
utiliser des avertissements ;
utiliser Hash::Util::FieldHash 'fieldhash';
fieldhash mon %time_for;
sous nouveau {
ma $classe = shift;
mon $self = bless \( mon $object ), $class;
$time_for{$self} = temps;
renvoie $self ;
}
sous-époque {
mon $self = shift;
retourner $time_for{$self};
}
mon $time = Heure->nouveau;
imprimer $time->epoch;
Pseudo-hachages
La fonctionnalité pseudo-hachage était une fonctionnalité expérimentale introduite dans les versions antérieures de Perl
et supprimé dans la version 5.10.0. Un pseudo-hachage est une référence de tableau accessible via
des clés nommées comme un hachage. Vous pourriez rencontrer du code qui l'utilise. Voir
champs pragma pour plus d'informations.
Utiliser perlobj en ligne avec les services onworks.net