Как я могу не благословить объект в Perl?

От perldoc-f благословляют:

bless REF,CLASSNAME

Эта функция говорит штуку, на которую ссылаются REF то, что это теперь
объект в CLASSNAME пакет.

Есть ли какой-либо способ получить несчастную структуру без ненужного копирования?

42
задан Sinan Ünür 24 February 2010 в 21:56
поделиться

3 ответа

Data :: Structure :: Util

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
39
ответ дан 26 November 2019 в 23:29
поделиться

Acme :: Curse :)

Обновление: Спасибо, Иван! Я перепутал модули. Собственно хотел дать ссылку на Acme :: Damn :))

P. S. См. Также Acme :: Sneeze :)

P. P. S. Это бесполезно, поэтому это Acme :: . См. Сообщение Брайана.

12
ответ дан 26 November 2019 в 23:29
поделиться

Data::Structure::Util имеет функцию unbless, которая сделает это за вас. Как отмечает Эрик, JSON::XS обычно не принимает благословенные ссылки (хотя я бы хотел, чтобы он просто игнорировал это и работал со структурой данных). В данном случае обойти это невозможно.

Но подумайте, почему вы считаете, что вам нужно снять благословение. Вы делаете это для одного из своих классов или для другого класса? Это звучит подозрительно похоже на "Неправильный поступок". Возможно, есть лучший способ.

У вас возникает та же проблема, что и при нарушении инкапсуляции, потому что вы должны предположить, что знаете внутреннюю структуру ссылки. Если вы собираетесь сделать это, вы можете просто проигнорировать объектно-ориентированные вещи и получить доступ к структуре напрямую.

Если вы собираетесь сделать это для своего класса, подумайте о том, чтобы предоставить метод для возврата структуры данных (которая не обязательно должна быть исходной структурой) вместо изменения объекта.

В последующем комментарии вы упомянули, что, возможно, вы делаете это, чтобы обойти некоторое поведение Template 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 );
29
ответ дан 26 November 2019 в 23:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: