如何在Perl中取消对象?

Eug*_*ash 43 oop perl bless

来自perldoc -f bless:

bless REF,CLASSNAME

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

有没有办法在没有不必要的复制的情况下获得无结构的结构?

Sin*_*nür 39

数据::结构::的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;
Run Code Online (Sandbox Code Playgroud)

输出:

My : 237356
HASH : 237356


bri*_*foy 29

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

但请考虑为什么你认为你需要解开它.你是为自己的班级还是其他班级做这个?这听起来像是错误的事情.可能有更好的方法.

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

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

您在后续评论中提到您可能正在执行此操作以绕过某些Template Toolkit行为.我根据情况以两种方式处理这种情况:

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

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


这是一个快速入侵,我TO_JSON在其中定义了一个in,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 );
Run Code Online (Sandbox Code Playgroud)

  • unbless通常很有帮助,就像你正在调试一个内部状态并希望在一个紧密循环中转储一个受祝福的对象...使用json :: xs因为Dumper慢了100倍,并且json :: xs不会转储祝福的对象....即使它只是一个hashref. (2认同)

小智 25

如果您知道对象的支持对象,则可以在不使用包的情况下执行此操作.

哈希

$obj = bless {}, 'Obj';
print ref $obj, "\n";
$obj = { %$obj };
print ref $obj, "\n";
Run Code Online (Sandbox Code Playgroud)

排列

$obj = bless [], 'Obj';
print ref $obj , "\n";
$obj = [ @$obj ];
print ref $obj, "\n";
Run Code Online (Sandbox Code Playgroud)

纯量

$obj = bless \$a, "Obj";
print ref $obj, "\n";
$obj = \${ $$obj };
print ref $obj, "\n";
Run Code Online (Sandbox Code Playgroud)

  • 这只适用于只有最高级别的祝福.散列值或数组元素本身可能是受祝福的引用. (3认同)
  • +1因为这确切地解决了我的问题,即我只是想"暂时"访问对象的基础数据结构(哈希),以便轻松地将其转移到YAML :: Tiny. (2认同)

cod*_*lic 12

Acme ::诅咒 :)

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

PS参见Acme :: Sneeze :)

PPS没有实际用途,这就是它的原因Acme::.见布莱恩的帖子.

  • 在http://www.sysadmin.recovery中得知迈克安德鲁斯:"Perl已经_bless_了,我们知道它做了什么,对吗?Perl也应该有_smite_,我们也应该知道它应该做什么.如果有更多的语言实现了_smite_,剩下的程序员会比当前的平均水平更好." (6认同)