« FlashLite: 定数を変数に入れる基準 | メイン | FlashLite: SWF で FizzBuzz ってみた »

Perl: オブジェクトのunbless

perlのblessはオブジェクトにクラス名をマッピングする命令です。

my $a = bless {}, "AA::BB::CC";
print ref($a), "\n";

を実行すると、AA::BB::CCが表示されます。

ほかの名前でblessし直すとその名前で古い対応関係が上書きされます。ではその対応関係を解除するにはどうすればよいのでしょう。bless $a, "HASH"などとすれば、ref関数の結果はblessする前と同じになりますが、依然としてblessされたままです。たとえば、Scalar::Utilのblessed命令を実行すると、blessされたままであることがわかります。

blessの解除を行うために、Data::Structure::Utilパッケージのunblessという命令が使えます。

use Scalar::Util qw(blessed);
use Data::Structure::Util qw(unbless);
my $a = bless {}, "TEST";
unbless($a);
print "Hello\n" if blessed($a);

これを実行しても、Helloは表示されません。同じ用途で、Acme::Damnのdamnも使えます。

use Scalar::Util qw(blessed);
use Acme::Damn qw(damn);
my $b = bless {}, "TEST";
damn($b);
print "Hello\n" if blessed($b);

これも、同じ結果になります。どちらも、ソースを見てみるとperlだけではこれは記述できなくて、xsのなかで、

SvOBJECT_off(sv);

を実行しています。blessされたオブジェクトであることを表しているフラグを0にしているわけです。一旦blessしたオブジェクトに対して、そのblessを解除するのって、実はそんなに簡単なことではないんですね。

トラックバック

このエントリーのトラックバックURL:
http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-tbp.cgi/1218

コメントを投稿