我怎样才能在Perl中unbless一个对象?

来自perldoc -f保佑 :

bless REF,CLASSNAME

这个函数告诉REF现在引用的东西
CLASSNAME包中的一个对象。

没有不必要的复制,有没有办法获得一个没有结构的结构?

数据::结构::的Util

unbless($ref)

从传递的数据结构中find的任何对象中移除祝福。

 #!/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; 

输出:

 我的:237356
 HASH:237356 

Data :: Structure :: Util有一个unbless函数可以为你做。 正如Erik指出的那样, JSON :: XS通常不会接受有福的引用(尽pipe我希望它会忽略这个并处理数据结构)。 在这种情况下没有办法。

但是,考虑一下为什么你觉得你需要把它弄坏。 你是为了你自己的class还是不同的class? 这听起来像是错误的事情。 可能有更好的办法。

你有和打破封装一样的问题,因为你必须假设你知道引用的内部结构是什么。 如果你打算这样做,你可以忽略面向对象的东西,直接访问结构。

如果你要为自己的类做这个,考虑提供一个方法来返回一个数据结构(不一定是原始结构)而不是改变对象。

你在后续评论中提到,你可能会这样做来解决一些模板工具包的行为。 根据情况,我有两种方式:

  • 只需将所需的数据传递给模板而不是整个对象。
  • 将方法添加到对象以获取模板中需要的数据。

Perl是DWIM,但TT甚至是DWIMmier,这有时是不幸的。


这是一个快速TO_JSON ,我在UNIVERSAL定义了一个TO_JSON ,所以它适用于所有对象。 它会进行深层复制,将其解开并返回数据结构。

 #!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 :: Damn :))

PS另请参阅Acme ::打喷嚏 🙂

PPS它没有真正的用途,这就是为什么它是Acme:: 。 见布莱恩的post。