Wie kann ich unbless ein Objekt in Perl?
Frage
bless REF,CLASSNAME
Diese Funktion teilt das Dingen von
REF
verwiesen, dass es jetzt ist
ein Objekt imCLASSNAME
Paket.
Gibt es eine Möglichkeit, um eine unblessed Struktur ohne unnötiges Kopieren zu erhalten?
Lösung
unbless($ref)
Nehmen Sie den Segen von allen Objekten innerhalb der übergebenen Datenstruktur gefunden.
#!/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;
Ausgabe:
My : 237356 HASH : 237356
Andere Tipps
Data :: Struktur :: Util eine unbless
Funktion hat, die es tun für Sie. Wie Erik weist darauf hin, JSON :: XS normalerweise nicht gesegnet Referenzen akzeptieren (obwohl ich wünschte, es würde einfach ignorieren das und befassen sich mit der Datenstruktur). Es gibt keinen Weg, um es in diesem Fall.
Aber darüber nachdenken, warum denken Sie, Sie unbless brauchen. Tun Sie dies für einen Ihrer eigenen Klassen oder einer anderen Klasse? Das klingt verdächtig nach dem falschen Sache zu Do. Es könnte ein besserer Weg geben.
Sie haben das gleiche Problem wie Verkapselung zu brechen, weil Sie müssen davon ausgehen, dass Sie wissen, was die innere Struktur der Referenz. Wenn Sie das tun werden, können Sie einfach ignorieren die objektorientierte Sachen und den Zugang der Struktur direkt an.
Wenn Sie vorhaben, dies für die eigene Klasse tun, denken Sie daran, ein Verfahren, eine Datenstruktur zurück (die nicht die ursprüngliche Struktur sein muss), statt das Objekt zu ändern.
erwähnen Sie in einem Follow-up-Kommentar, dass Sie dies tun könnten einige Template Toolkit Verhalten zu umgehen. Ich hatte diese Situation auf zwei Arten je nach Situation:
- Es werden nur die Daten übergeben Sie anstelle des gesamten Objekts an der Vorlage benötigen.
- Fügen Sie Methoden für das Objekt die Daten erhalten Sie in der Vorlage werden soll.
Perl ist DWIM, aber TT ist auch DWIMmier, die unglückliche manchmal ist.
Hier ist eine schnelle Hack, wo ich eine TO_JSON
in UNIVERSAL
definieren, so dass es für alle Objekte gilt. Es macht eine tiefe Kopie, unblesses es und gibt die Datenstruktur.
#!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 );
Wenn Sie wissen, was Ihre Aufgabe durch gesichert ist, könnten Sie dies tun, ohne Pakete zu verwenden.
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";
Update: Danke, Ivan! I gemischt Module. Eigentlich wollte ich einen Link geben Gipfel :: Verdammt :))
P. . S finden Sie unter Gipfel :: Sneeze :)
P. P. S. Es hat keine wirkliche Verwendung, das ist, warum es Acme::
. Siehe Brians Post.