Comment puis-je débloquer un object en Perl?

De perldoc -f bless :

bless REF,CLASSNAME

Cette fonction indique à la chose référencée par REF qu’elle est maintenant
un object dans le package CLASSNAME .

Existe-t-il un moyen d’obtenir une structure sans concession sans copie inutile?

Données :: Structure :: Util

unbless($ref)

Supprimez la bénédiction des objects trouvés dans la structure de données transmise.

 #!/usr/bin/perl use ssortingct; use warnings; use Scalar::Util qw( refaddr ); use Data::Structure::Util qw( unbless ); my $x = bless { a => 1, b => 2 } => 'My'; printf "%s : %s\n", ref $x, refaddr $x; unbless $x; printf "%s : %s\n", ref $x, refaddr $x; 

Sortie:

  Mon: 237356
 HASH: 237356 

Data :: Structure :: Util a une fonction sans unbless qui le fera pour vous. Comme Erik le fait remarquer, JSON :: XS n’acceptera normalement pas les références bénies (bien que je souhaite qu’il ignore simplement cela et traite de la structure des données). Il n’y a aucun moyen de contourner cela dans ce cas.

Mais considérez pourquoi pensez-vous que vous devez le débloquer. Faites-vous cela pour l’une de vos propres classes ou pour un autre cours? Cela ressemble étrangement à The Wrong Thing To Do. Il pourrait y avoir un meilleur moyen.

Vous avez le même problème que la rupture de l’encapsulation, car vous devez supposer que vous connaissez la structure interne de la référence. Si vous allez faire cela, vous pouvez simplement ignorer les éléments orientés object et accéder directement à la structure.

Si vous envisagez de le faire pour votre propre classe, envisagez de fournir une méthode pour renvoyer une structure de données (qui ne doit pas nécessairement être la structure d’origine) au lieu de modifier l’object.

Vous mentionnez dans un commentaire de suivi que vous pourriez le faire pour contourner le comportement de Template Toolkit. J’ai eu cette situation de deux manières en fonction de la situation:

  • Ne transmettez les données nécessaires au modèle qu’à la place de l’object entier.
  • Ajoutez des méthodes à l’object pour obtenir les données souhaitées dans le modèle.

Perl est DWIM, mais TT est même DWIMmier, ce qui est parfois regrettable.


Voici un hack rapide où je définis un TO_JSON dans UNIVERSAL pour qu’il s’applique à tous les objects. Il effectue une copie en profondeur, le débloque et renvoie la structure de données.

 #!perl use v5.10; sub UNIVERSAL::TO_JSON { my( $self ) = shift; use Storable qw(dclone); use Data::Structure::Util qw(unbless); my $clone = unbless( dclone( $self ) ); $clone; } my $data = bless { foo => bless( [], 'Local::Array' ), quack => bless( { map { $_ => bless [$_, $_**2], 'Local::Array' } grep { is_prime } 1 .. 10 }, 'Local::Hash' ), }, 'Local::Hash'; use JSON::XS; my $jsonner = JSON::XS->new->pretty->convert_blessed(1); say $jsonner->encode( $data ); 

Si vous savez par quoi votre object est sauvegardé, vous pouvez le faire sans utiliser de paquet.

Hacher

 $obj = bless {}, 'Obj'; print ref $obj, "\n"; $obj = { %$obj }; print ref $obj, "\n"; 

Tableau

 $obj = bless [], 'Obj'; print ref $obj , "\n"; $obj = [ @$obj ]; print ref $obj, "\n"; 

Scalaire

 $obj = bless \$a, "Obj"; print ref $obj, "\n"; $obj = \${ $$obj }; print ref $obj, "\n"; 

Acme :: Malédiction 🙂

Mise à jour: Merci Ivan! J’ai mélangé des modules. En fait je voulais donner un lien vers Acme :: Damn :))

PS Voir aussi Acme :: Sneeze 🙂

PPS Il n’a pas de réelle utilité, c’est pourquoi c’est Acme:: . Voir le post de Brian.