どうにも腑に落ちない現象にでくわしたのでメモ。まず、以下のようなモジュールがあったとする。

# Foo.pm
package Foo;
use strict;

sub work {
    # なんたらかんたら
}

# Hoge.pm
package Hoge;
use strict;

sub work {
    die "ABSTRACT METHOD";
}

# Fuga.pm
package Fuga;
use strict;
use base qw(Hoge);
use Fop;

sub work {
    my $self = shift;
    my $foo = Foo->new();
    $foo->work();
    # なんたらかんたら
}

要点をまとめると、

  • Foo、Hoge、Fugaがある
  • FooもHogeもFugaもworkメソッドがある
  • Fugaはuse baseでHogeを継承していて、workメソッドをオーバーライドしてる
  • Hoge、FugaとFooの間には何の関係もないが、Fugaの中でFooを使ってる
  • use Fooのところをtypoしてる(ちなみにFop.pmなどというファイルはない)

という状況があるってのが前提。俺は何をしたかったかというと、$fuga->workってやるとFooを使った何らかの処理をして欲しかった。ところがuse Fopとかしちゃってる為、これはエラーが出て実行できないコードだった(ということに気付いたのは実は大分後の話なんだけど)。これだけなら大した問題じゃない。

ところが、実際にどんなことが起きたかというと、こうだった。

  • Foga.pmのuse Foo以降のコードが無視されるが、この時点ではエラーが出ない
  • Hoge::workが実行され、"ABSTRACT METHOD"というエラーメッセージを吐いて死ぬ

何でこんな挙動になるのか理解が出来なかった。useのところでエラーが出て死ぬんならまぁ、「まーたtypoってるよ、俺ってばドジっ子で低能でワーキングプアだなぁ、あはは」でいい話なんだけど、同じくHogeをuse baseしてる別モジュールは全く何の問題もなく動き、にもかかわらずFugaは自分のworkを無視して親であるHogeの方を読みに行くってのが意味不明で、そのせいでtypoだって気付くまでに時間がかかってしまった。

結局、typoを直したら期待した通りに動いたし、そもそも設計が微妙なので後で直そうとは思ってるんだけど、なんつーか、気持ち悪い。すごいもやもやした感触が残る。うーん?なんだこれ?TheSchwartz絡みなのかなぁ、この妙な挙動。あとで調べてみよう。