46

perldoc -f bless

bless REF,CLASSNAME

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

有没有什么方法可以在没有不必要的复制的情况下获得一个不受祝福的结构?

4

4 回答 4

39

数据::结构::实用程序

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;

输出:

我的:237356
哈希:237356
于 2010-02-24T22:01:05.577 回答
34

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

但是考虑一下为什么你认为你需要取消祝福它。您是为自己的班级还是其他班级做这件事?这听起来有点像“做错了事”。可能有更好的方法。

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

如果您要为自己的类执行此操作,请考虑提供一种方法来返回数据结构(不必是原始结构),而不是更改对象。

您在后续评论中提到您可能这样做是为了解决某些模板工具包行为。根据情况,我有两种情况:

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

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


这是一个快速技巧,我在其中定义了一个TO_JSONin,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 );
于 2010-02-24T22:21:27.617 回答
27

如果你知道你的对象是由什么支持的,你可以在不使用包的情况下做到这一点。

哈希

$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";
于 2011-08-31T22:54:15.537 回答
12

Acme::诅咒:)

更新:谢谢你,伊万!我混合了模块。其实我想给一个链接到 Acme::Damn :))

PS另见Acme::Sneeze :)

PPS它没有真正的用处,这就是为什么它是Acme::. 见布赖恩的帖子。

于 2010-02-24T20:49:49.520 回答