如何在Perl中解除对象的绑定?
发件人:如何在Perl中解除对象的绑定?,perl,oop,bless,Perl,Oop,Bless,发件人: bless REF,CLASSNAME 此函数告诉REF引用的东西现在是 CLASSNAME包中的对象 有没有任何方法可以在不进行不必要的复制的情况下获得无版权的结构?: 更新:谢谢你,伊万!我把模块弄混了。实际上我想给你一个链接:)) 另请参见:) p.p.S.它没有实际用途,这就是为什么它是Acme::。请参阅brian的帖子。 unbless($ref) 从传递的数据结构中找到的任何对象中删除祝福 #!perl use v5.10; sub UNIVERSAL::TO_JSON
bless REF,CLASSNAME
此函数告诉REF
引用的东西现在是CLASSNAME
包中的对象
有没有任何方法可以在不进行不必要的复制的情况下获得无版权的结构?:
更新:谢谢你,伊万!我把模块弄混了。实际上我想给你一个链接:))
另请参见:)
p.p.S.它没有实际用途,这就是为什么它是Acme::
。请参阅brian的帖子。
unbless($ref)
从传递的数据结构中找到的任何对象中删除祝福
#!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 );
输出:
My : 237356
HASH : 237356
我的电话:237356
HASH:237356有一个unbless
函数,可以为您执行此操作。正如Erik指出的,我们通常不会接受受祝福的引用(尽管我希望它能忽略这一点并处理数据结构)。在这种情况下没有办法解决
但是,为什么你认为你需要放弃它呢?你是为你自己的一个班还是另一个班?这听起来似乎是错误的做法。也许有更好的办法
您的问题与破坏封装相同,因为您必须假设您知道引用的内部结构是什么。如果要这样做,可以忽略面向对象的内容,直接访问结构
如果你要为你自己的类做这件事,考虑提供一种方法来返回一个数据结构(它不必是原来的结构),而不是改变对象。 您在后续的评论中提到,您这样做可能是为了避开某些模板工具包行为。根据具体情况,我有两种情况:
- 只将需要的数据传递给模板,而不是整个对象
- 向对象添加方法以获取模板中所需的数据
下面是一个快速破解,我在
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 \$a, "Obj";
print ref $obj, "\n";
$obj = \${ $$obj };
print ref $obj, "\n";
但是这个模块创建了对象的副本。Mike Andrews在alt.sysadmin.recovery中写道:“Perl已经有了bless,我们知道它的功能,对吧?Perl也应该有smite,我们也知道它应该做什么。如果更多的语言实现了smite,剩下的程序员将比当前的平均水平更好。”另请参见@Ether:例如,Template::Toolkit。点运算符
。
用于访问列表和哈希或调用对象方法。TT总是先尝试一个对象方法。FWIW我需要unbless
,因为YAML::Any::Dump()
将保留一个对象的神圣属性,我不想存储它,但有时我正在转储的数据散列是神圣的。另外,Moose->new
非常挑剔,不会把hashref当作论点。是的,转储对象通常是原因。“你为什么需要这个”的评论经常是由一个理论家说出来的. 它同时是无益的,居高临下的,暗示着无知。好吧,“你为什么需要这个”通常是试图找到真正的问题,因为人们问的是一个他们认为他们需要的解决方案,而不是一个原因。在这种情况下,最初的帖子对建议的解决方案没有任何动机。+1因为这正好解决了我的问题,即我只想“临时”访问对象的底层数据结构(散列),以便使用YAML::Tiny轻松转储它。这只有在最高层得到支持的情况下才有效。散列值或数组元素本身可能是受祝福的引用。unbless通常很有用,例如当您调试内部状态并希望在紧循环中转储受祝福的对象时…使用json::xs,因为转储程序的速度慢了100倍,而json::xs不会转储受祝福的对象。。。。即使它只是一个hashref。事实上,JSON::XS是我无法用其他方法实现的地方。谢谢,我已经更新了我的答案。
$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";