代码之家  ›  专栏  ›  技术社区  ›  Eugene Yarmash

如何在Perl中取消对象的绑定?

  •  41
  • Eugene Yarmash  · 技术社区  · 15 年前

    perldoc -f bless :

    bless REF,CLASSNAME

    此函数告诉 REF 就是现在
    中的对象 CLASSNAME 包裹。

    是否有任何方法可以在不进行不必要的复制的情况下获得无抵押结构?

    4 回复  |  直到 9 年前
        1
  •  38
  •   Sinan Ünür    15 年前

    Data::Structure::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;
    

    输出:

    My : 237356
    HASH : 237356
        2
  •  28
  •   brian d foy    11 年前

    Data::Structure::Util 有一个 unbless 为您提供的功能。埃里克指出, JSON::XS 通常不会接受有福的引用(尽管我希望它忽略这一点并处理数据结构)。在这种情况下没有办法解决。

    但想想为什么你认为你需要解开它。你是为你自己的一个班还是另一个班做这个?这听起来像是做错事。也许还有更好的办法。

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

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

    您在后续评论中提到,您可能这样做是为了绕过一些模板工具箱行为。根据具体情况,我有两种情况:

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

    Perl是dwim,但tt甚至是dwimimer,这有时是不幸的。


    这里有一个快速的黑客,我定义了一个 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 );
    
        3
  •  21
  •   RandomMonkey    13 年前

    如果您知道您的对象是由什么支持的,那么您可以在不使用包的情况下执行此操作。

    搞砸

    $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";
    
        4
  •  12
  •   brian d foy    15 年前

    Acme::Curse :)

    更新: 谢谢你,伊凡!我把模块弄混了。实际上我想给你一个链接 Acme::Damn :)

    P.S. 也见 Acme::Sneeze :)

    P.P.S.公司 它没有真正的用途,所以 Acme:: .看布莱恩的帖子。

    推荐文章