北海道苫小牧市出身の初老PGが書くブログ

永遠のプログラマを夢見る、苫小牧市出身のおじさんのちらしの裏

overloadとblessの関係で変な挙動?

perl 5.8.8 で overloadしてるオブジェクトをblessし直すと、おかしな挙動になることがあるようです。

正常な例

まずは、うまく行く例。

# オーバーロードすると、出力を変えられる
use overload '""' => sub {"O1"};
my $o1 = bless {};
print $o1, "\n";

# 別のクラスにすると、デフォルトの出力ハンドラに戻る
bless $o1, 'Hoge';
print "REF: ", ref($o1), "\n";
print $o1, "\n";

出力は以下です。

O1
REF: Hoge
Hoge=HASH(0x800d80)

駄目な例

ところが、このリファレンスを別の変数にコピーして、コピー側で別のクラスにblessするとおかしくなります。

# オーバーロードすると、出力を変えられる
use overload '""' => sub {"O1"};
my $o1 = bless {};
print $o1, "\n";

# 別のクラスにすると、デフォルトの出力ハンドラに戻る
my $o2 = $o1;
bless $o2, 'Hoge';
print "REF: ", ref($o1), "\n";
print $o1, "\n";
O1
REF: Hoge
Operation """": no method found, argument in overloaded package Hoge at - line 10.

refした結果は別のオブジェクトになってますが、""に対するハンドラがないと怒られます。

考察

予想ですけど、overloadプラグマは内部でSVとかIVとかRVとかにMAGICみたいのでごにょごにょうしてこの機能を実現しているために*1、コピーしたスカラの面倒までは見切れてないんじゃないでしょうか。XSまったくわからないので、詳細な解説は親切なXS Niteのどなたかにお任せしますm(_ _)m。

参考記事

こういうこと考えると今回の事例が影響があるかもしれませんね。

*1:知ってる単語並べただけです><