« 2007年03月 | メイン | 2007年05月 »

2007年04月20日

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を解除するのって、実はそんなに簡単なことではないんですね。