Historique de la question :
Depuis la première version de Perl 5, le langage prend en charge un modèle d'objet élémentaire via le mécanisme de liaison des références à un package (blessing). En Perl, les objets sont des références ordinaires (vers un hachage, un tableau ou un scalaire) "béatifiées" par la fonction bless, ce qui permet au système de trouver des méthodes via le package (namespace).
Problème :
Les références non béatifiées restent des structures de données ordinaires, et essayer d'appeler une méthode dessus entraîne des erreurs d'exécution. Un programmeur, sans prêter attention au type de référence, risque de manipuler accidentellement l'intérieur de l'objet, violant ainsi l'encapsulation. De plus, travailler avec l'opération de déréférencement "brute" {} ou @{} sans contrôle peut provoquer des bugs difficiles à détecter.
Solution :
Créer correctement des objets uniquement via bless, puis accéder aux données de l'objet uniquement par déréférencement, en vérifiant le type à l'aide du module Scalar::Util (ref, blessed). Il est toujours préférable d'éviter l'accès direct aux structures (par exemple, $obj->{key}) en dehors des méthodes de la classe et de mettre en œuvre des accesseurs (getter/setter) pour le contrôle.
Exemple de code :
package Animal; sub new { my $class = shift; my $self = { name => shift }; bless $self, $class; return $self; } sub name { my $self = shift; $self->{name} = shift if @_; return $self->{name}; } my $dog = Animal->new("Rex"); print $dog->name; # sûr via accessor print $dog->{name}; # accès direct, déconseillé
Caractéristiques clés :
blessed ou ref réduisent significativement le nombre de bugs.Une référence simple à un hachage peut-elle être utilisée comme objet sans bless ?
Non, sans appel à bless, la référence n'a pas d'association avec un package, et Perl ne trouvera pas les méthodes (il y aura une erreur "Can't call method"), malgré une structure interne identique.
Comment déterminer en toute sécurité si une variable est vraiment un objet et non simplement une référence ?
Utiliser la fonction Scalar::Util::blessed($obj) pour vérifier si la référence est béatifiée. Seules les références béatifiées sont considérées comme des objets.
use Scalar::Util 'blessed'; my $obj = {}; print blessed($obj) ? 'yes' : 'no'; # affichera 'no'
Peut-on appeler une méthode sur une référence non-objet sans erreurs ?
Appeler une méthode sur une référence non béatifiée entraînera une erreur fatale : Perl s'attend à ce que la référence connaisse son package. Les mécanismes AUTOLOAD et les chargements dynamiques sont des exceptions, mais cela constitue un antipattern qui conduit à des erreurs.
Un jeune développeur crée manuellement une structure $person = {name => 'Vasya'} et oublie d'appeler bless, puis essaie d'appeler $person->name(), ce qui entraîne une erreur d'exécution.
Avantages :
Inconvénients :
Dans le code, bless est toujours appelé lors de la création de l'objet et seule la méthode name() est utilisée pour accéder aux données. La vérification via blessed() permet de gérer les erreurs avant l'exécution des méthodes.
Avantages :
Inconvénients :