От perldoc -f bless:
bless REF,CLASSNAME
Эта функция сообщает thingy, на которую ссылается
REF
, что теперь она объект в пакетеCLASSNAME
.
Есть ли какой-либо способ получить безболезненную структуру без ненужного копирования?
От perldoc -f bless:
bless REF,CLASSNAME
Эта функция сообщает thingy, на которую ссылается
REF
, что теперь она объект в пакетеCLASSNAME
.
Есть ли какой-либо способ получить безболезненную структуру без ненужного копирования?
unbless($ref)
Удалите благословение от любых объектов, найденных в переданной структуре данных.
#!/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;
Вывод:
My : 237356 HASH : 237356
Data:: Structure:: Util имеет функцию unbless
, которая сделает это за вас. Как отмечает Эрик, JSON::XS обычно не принимает благословенные ссылки (хотя я бы хотел, чтобы это просто проигнорировало это и касалось структуры данных), В этом случае нет никакого пути.
Но подумайте, почему вы считаете, что вам нужно его беспуть. Вы делаете это для одного из своих классов или другого класса? Это звучит подозрительно, как The Wrong Thing To Do. Возможно, лучший способ.
У вас такая же проблема, как и разрыв инкапсуляции, потому что вы должны предположить, что знаете, что такое внутренняя структура ссылки. Если вы собираетесь это сделать, вы можете просто игнорировать объектно-ориентированные вещи и напрямую обращаться к структуре.
Если вы собираетесь сделать это для своего собственного класса, подумайте о том, чтобы предоставить метод для возврата структуры данных (которая не должна быть исходной структурой) вместо изменения объекта.
Вы упомянули в последующем комментарии, что вы можете сделать это, чтобы обойти некоторые действия с шаблоном Toolkit. У меня была эта ситуация двумя способами в зависимости от ситуации:
Perl - это DWIM, но TT - это даже DWIMmier, что иногда бывает неудачным.
Вот быстрый хак, где я определяю TO_JSON
в UNIVERSAL
, поэтому он применим ко всем объектам. Он делает глубокую копию, не разбивает ее и возвращает структуру данных.
#!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 );
Если вы знаете, что поддерживает ваш объект, вы можете сделать это без использования пакетов.
Хэш
$obj = bless {}, 'Obj';
print ref $obj, "\n";
$obj = { %$obj };
print ref $obj, "\n";
Массив
$obj = bless [], 'Obj';
print ref $obj , "\n";
$obj = [ @$obj ];
print ref $obj, "\n";
Скалярное
$obj = bless \$a, "Obj";
print ref $obj, "\n";
$obj = \${ $$obj };
print ref $obj, "\n";
Обновление: Спасибо, Иван! Я перепутал модули. На самом деле я хотел дать ссылку на Acme::Damn:))
Р. S. См. Также Acme::Sneeze:)
Р. P. S. Он не имеет реального использования, поэтому он Acme::
. См. Сообщение Брайана.