题
bless REF,CLASSNAME
该函数告诉所引用的事物
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
其他提示
数据::结构::实用程序 有一个 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 );
如果你知道你的目标是通过支持,你可以做到这一点,而不使用的包。
哈希
$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 ::诅咒 :)
更新:谢谢,伊万!我用了模块。其实我想给一个链接到的Acme ::该死:))
<强> P上。 :S 查看还的Acme ::喷嚏:)
<强> P上。 P. S上。它没有真正使用,这就是为什么它的Acme::
。见布赖恩的帖子。