Od perldoc -f bless:Jak mogę unbless obiektu w Perl?
bless REF,CLASSNAME
Funkcja ta opowiada thingy odwołuje
REF
że teraz
przedmiot w paczceCLASSNAME
.
Czy istnieje sposób na uzyskanie niezabezpieczonej struktury bez niepotrzebnego kopiowania?
Od perldoc -f bless:Jak mogę unbless obiektu w Perl?
bless REF,CLASSNAME
Funkcja ta opowiada thingy odwołuje
REF
że teraz
przedmiot w paczceCLASSNAME
.
Czy istnieje sposób na uzyskanie niezabezpieczonej struktury bez niepotrzebnego kopiowania?
unbless($ref)
Usuń błogosławieństwo od wszelkich przedmiotów znalezionych w przekazanym struktury danych.
#!/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;
wyjściowa:
My : 237356 HASH : 237356
Acme::Curse :)
Aktualizacja: Dziękuję, Ivan! Wymieszałem moduły. Właściwie chciałem dać link do Acme::Damn :))
P. S. Zobacz również Acme::Sneeze :)
P. P. S. To nie ma rzeczywistego wykorzystania, dlatego to Acme::
. Zobacz post Briana.
Ale ten moduł tworzy kopię obiektu. –
Przypisany Mike'owi Andrewsowi w alt.sysadmin.recovery: "Perl już ma _bless_ i wiemy, co robi, tak? Perl powinien również mieć _smite_, i wiemy, co powinien on zrobić, gdyby więcej języków miało _smite_ implementowane, pozostali programiści byliby lepsi niż obecna średnia. " –
Data::Structure::Util ma unbless
funkcję, która zrobi to za Ciebie. Jak wskazuje Erik, JSON::XS zwykle nie przyjmuje błogosławionych odniesień (chociaż żałuję, że po prostu nie zignoruje tego i nie zajmie się strukturą danych). W tym przypadku nie da się obejść.
Ale zastanów się, dlaczego uważasz, że nie powinieneś tego robić. Czy robisz to dla jednej z twoich własnych klas lub innej klasy? Brzmi to podejrzanie jak The Wrong Thing To Do. Może być lepszy sposób.
Masz ten sam problem co łamanie enkapsulacji, ponieważ musisz założyć, że wiesz, jaka jest wewnętrzna struktura odwołania. Jeśli zamierzasz to zrobić, możesz po prostu zignorować obiekty zorientowane obiektowo i uzyskać bezpośredni dostęp do struktury.
Jeśli zamierzasz to zrobić dla własnej klasy, rozważ dostarczenie metody zwracania struktury danych (która nie musi być oryginalną strukturą) zamiast zmiany obiektu.
Wspominasz w kolejnym komentarzu, że możesz to zrobić, aby obejść zachowanie szablonu Toolkit. Miałem tę sytuację na dwa sposoby w zależności od sytuacji:
Perl to DWIM, ale TT to nawet DWIMmier, co czasami jest niefortunne.
Oto szybki hack, gdzie mogę zdefiniować TO_JSON
w UNIVERSAL
więc ma ona zastosowanie do wszystkich obiektów. Tworzy głęboką kopię, unsorbuje ją i zwraca strukturę danych.
#!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);
+1 za uzyskanie prawdziwego problemu. – Ether
unbless jest często pomocny, na przykład podczas debugowania stanu wewnętrznego i chcesz zrzucić błogosławiony obiekt w ciasnej pętli ... z json :: xs, ponieważ Dumper jest 100 razy wolniejszy, a json :: xs nie zrzuca błogosławiony przedmiot ... nawet jeśli to tylko hashref. –
Rzeczywiście, JSON :: XS jest jedynym miejscem, w którym nie mogłem tego zrobić w żaden inny sposób. Dzięki, zaktualizowałem swoją odpowiedź. –
Jeśli wiesz, co obiekt jest wspierany, możesz to zrobić bez użycia pakietów.
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";
Skalar
$obj = bless \$a, "Obj";
print ref $obj, "\n";
$obj = \${ $$obj };
print ref $obj, "\n";
+1, ponieważ to właśnie rozwiązało mój problem, a mianowicie po prostu chciałem "tymczasowo" uzyskać dostęp do podstawowej struktury danych obiektu (Hash), aby łatwo zrzucić go za pomocą YAML :: Tiny. –
Działa to tylko wtedy, gdy błogosławiony jest tylko najwyższy poziom. Wartości mieszania lub elementy tablicy mogą same być błogosławionymi odniesieniami. –
Zobacz również http://www.perlmonks.org/?node_id=183348 –
@Ether: Na przykład, Szablon :: Toolkit. Operator kropki ''.'' służy do uzyskiwania dostępu do list i skrótów lub do wywoływania metod obiektowych. TT zawsze próbuje najpierw metody obiektowej. –
FWIW Potrzebuję 'unbless' ponieważ' YAML :: Any :: Dump() 'zachowa błogosławioną naturę obiektu, nie chcę tego przechować, ale czasami skróty danych, które zrzucam są błogosławione. Również "Łoś-> nowy" jest bardzo wybredny i nie bierze błogosławionego haszyszu do kłótni. – Schwern