46

perldoc -f blessから:

bless REF,CLASSNAME

この関数は、によって参照されるREFものに、それがパッケージ
内のオブジェクトになったことを通知します。CLASSNAME

不必要なコピーをせずに、祝福されていない構造を取得する方法はありますか?

4

4 に答える 4

39

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;

出力:

私:237356
ハッシュ:237356
于 2010-02-24T22:01:05.577 に答える
34

Data :: Structure :: Utilには、unblessそれを実行する関数があります。Erikが指摘しているように、JSON :: XSは通常、祝福された参照を受け入れません(ただし、それを無視してデータ構造を処理することを望みます)。この場合、それを回避する方法はありません。

しかし、なぜあなたはそれを祝福する必要があると思いますか?あなたはあなた自身のクラスの1つまたは別のクラスのためにこれをしていますか?これは疑わしいことに、The Wrong ThingToDoのように聞こえます。より良い方法があるかもしれません。

参照の内部構造が何であるかを知っていると想定する必要があるため、カプセル化を解除するのと同じ問題が発生します。これを行う場合は、オブジェクト指向のものを無視して、構造に直接アクセスできます。

独自のクラスに対してこれを行う場合は、オブジェクトを変更する代わりに、データ構造(元の構造である必要はありません)を返すメソッドを提供することを検討してください。

フォローアップコメントで、TemplateToolkitの動作を回避するためにこれを行っている可能性があると述べています。私は状況に応じて2つの方法でこの状況になりました:

  • オブジェクト全体ではなく、必要なデータのみをテンプレートに渡します。
  • オブジェクトにメソッドを追加して、テンプレートに必要なデータを取得します。

PerlはDWIMですが、TTはDWIMmierでさえあり、それは時々不幸です。


これは、すべてのオブジェクトに適用されるよう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 );
于 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 :: Curse :)

更新:ありがとう、Ivan!モジュールを混同しました。実際、私はAcme :: Damn :))へのリンクを提供したかった

PS Acme ::Sneeze :)も参照してください

PPSそれは実際には使用されないので、それが理由Acme::です。ブライアンの投稿を参照してください。

于 2010-02-24T20:49:49.520 に答える