Question

De perldoc -f bénir :

  

bless REF,CLASSNAME

     

Cette fonction indique la référence par REF thingy qu'il est maintenant
          un objet dans le package de CLASSNAME.

Est-il possible d'obtenir une structure unblessed sans copie inutile?

Était-ce utile?

La solution

données :: Structure :: Util

  

unbless($ref)

     

Retirez le bienfait de tous les objets trouvés dans la structure de données transmis.

#!/usr/bin/perl

use strict; 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:

My : 237356
HASH : 237356

Autres conseils

données :: Structure :: Util a une fonction de unbless qui le fera pour vous. Comme le souligne Erik sur, JSON :: XS ne sera normalement pas accepter des références bénies (bien que Je voudrais qu'il serait tout simplement ignorer et faire face à la structure de données). Il n'y a pas moyen de contourner cela dans ce cas.

Mais considérez pourquoi pensez-vous que vous devez unbless il. Est-ce que vous faites cela pour un de vos propres classes ou une autre classe? Cela ressemble étrangement à la mauvaise chose à Do. Il pourrait y avoir une meilleure façon.

Vous avez le même problème que la rupture encapsulation parce que vous devez supposer que vous savez ce que la structure interne de la référence est. Si vous allez le faire, vous pouvez simplement ignorer les choses orientée objet et accéder à la structure directement.

Si vous allez faire pour votre propre classe, envisager de fournir une méthode pour retourner une structure de données (qui ne doit pas être la structure d'origine) au lieu de changer l'objet.

Vous mentionnez dans un commentaire de suivi que vous pourriez faire cela pour contourner certains comportements de Template Toolkit. J'ai eu cette situation de deux façons selon la situation:

  • Ne dépassez les données nécessaires au modèle au lieu de l'objet entier.
  • Ajouter des méthodes à l'objet pour obtenir les données que vous voulez dans le modèle.

Perl est dwim, mais TT est encore DWIMmier, ce qui est regrettable parfois.


Voici un hack rapide où je définis un TO_JSON en UNIVERSAL il applique à tous les objets. Il fait une copie en profondeur, unblesses, et retourne 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 ce que votre objet est soutenu par, vous pouvez le faire sans utiliser les paquets.

Hash

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

array

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

Scalar

$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 :: Bon sang :))

P. . S Voir aussi Acme :: Sneeze :)

P. P. S. Il n'a pas d'usage réel, c'est pourquoi il est Acme::. Voir le poste de brian.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top