¿Cómo puedo unbless un objeto en Perl?
Pregunta
bless REF,CLASSNAME
Esta función le dice a la manivela de la que hace referencia
REF
que ahora es
un objeto en el paqueteCLASSNAME
.
¿Hay alguna manera de obtener una estructura sin bendecir sin copiar innecesario?
Solución
de datos :: Estructura :: Util
unbless($ref)
Eliminar la bendición de cualquier objetos encontrados dentro de la estructura de datos pasado.
#!/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;
Salida:
My : 237356 HASH : 237356
Otros consejos
de datos :: Estructura :: Util tiene una función unbless
que lo hará para ti. Como señala Erik, JSON :: XS normalmente no aceptará referencias bendecido (aunque me gustaría que simplemente ignorar eso y trato con la estructura de datos). No hay manera de evitarlo en este caso.
Pero considere qué es lo que cree necesario que unbless ella. ¿Estás haciendo esto para una de sus propias clases o una clase diferente? Esto suena sospechosamente a la Cosa del mal Para Do. Puede haber una mejor manera.
Usted tiene el mismo problema que romper la encapsulación porque hay que asumir que usted sabe lo que la estructura interna de la referencia es. Si se va a hacer eso, puede simplemente ignorar la materia orientada a objetos y la estructura de acceso directamente.
Si usted va a hacer esto para su propia clase, considere la posibilidad de proporcionar un método para devolver una estructura de datos (que no tiene por qué ser la estructura original) en lugar de cambiar el objeto.
Usted menciona en un comentario de seguimiento que podría estar haciendo esto para obtener alrededor de un comportamiento Template Toolkit. Tenía esta situación de dos maneras dependiendo de la situación:
- Sólo pasar los datos que necesita para la plantilla en lugar de todo el objeto.
- Añadir métodos para el objeto de obtener los datos que desee en la plantilla.
Perl es DWIM, pero es aún TT DWIMmier, lo cual es lamentable veces.
Aquí hay un corte rápido cuando defino un TO_JSON
en UNIVERSAL
por lo que se aplica a todos los objetos. Se hace una copia profunda, unblesses, y devuelve la estructura de datos.
#!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 usted sabe lo que su objeto está respaldado por, usted podría hacer esto sin el uso de paquetes.
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";
Actualización: Gracias, Ivan! Me confundí módulos. En realidad quería dar un enlace a Acme :: Maldita :))
P. . S Acme :: estornudo :)
P. P. S. No tiene ningún uso real, es por eso que es Acme::
. Ver post de Brian.