SUPERは@ISAを探ってくれてるわけではない
これが動かなかったので調べたメモ。
strictはなしで。
*{"Foo::aiueo"} = sub { print "aiueo.\n" }; # Fooクラスのaiueoメソッド *{"Bar::new"} = sub { bless {}, "Bar" }; # Barクラスのコンストラクタ push @Bar::ISA, "Foo"; # BarはFooを継承 *{"Bar::aiueo"} = sub { my $self = shift; $self->SUPER::aiueo(); }; # Fooのaiueoメソッドを呼ぶ my $bar = Bar->new; $bar->aiueo; # Barのaiueoを通してFooのaiueoを呼ぶ
Can't locate object method "aiueo" via package "main::SUPER" at - line 5.
$self->SUPER::methodという書き方がイディオムになってしまって
なんとなく$selfのクラスの@ISA読んで辿ってくれてるのかなーと思ってたけど、
まったくそんなことはなかった。
perldoc perlobj
It is important to note that "SUPER" refers to the superclass(es) of
the current package and not to the superclass(es) of the object.
SUPER は、オブジェクトのスーパークラスではなく、
カレントパッケージ の スーパークラスを参照するということに注意することは重要です。
http://perldoc.jp/docs/perl/5.10.0/perlobj.pod
上記のコードのカレントパッケージは指定してないのでmainだ。
だから"main::SUPER"ってエラーで怒られているってことか。
でもなんとかしたい
他のmroみたいなnextで何とかならないかなーと思ってやってみた。
第2回 mro:次のメソッドはどこ?:モダンPerlの世界へようこそ|gihyo.jp … 技術評論社
NEXT
use NEXT; *{"Foo::aiueo"} = sub { print "aiueo.\n" }; *{"Bar::new"} = sub { bless {}, "Bar" }; push @Bar::ISA, "Foo"; *{"Bar::aiueo"} = sub { my $self = shift; $self->NEXT::aiueo(); }; my $bar = Bar->new; $bar->aiueo;
Can't call NEXT::aiueo from main::__ANON__ at - line 6
Class::C3
use Class::C3; *{"Foo::aiueo"} = sub { print "aiueo.\n" }; *{"Bar::new"} = sub { bless {}, "Bar" }; push @Bar::ISA, "Foo"; *{"Bar::aiueo"} = sub { my $self = shift; $self->next::aiueo(); }; my $bar = Bar->new; $bar->aiueo;
Can't locate object method "aiueo" via package "next" at - line 6.
mro
use mro 'c3'; *{"Foo::aiueo"} = sub { print "aiueo.\n" }; *{"Bar::new"} = sub { bless {}, "Bar" }; push @Bar::ISA, "Foo"; *{"Bar::aiueo"} = sub { my $self = shift; $self->next::aiueo(); }; my $bar = Bar->new; $bar->aiueo;
Can't locate object method "aiueo" via package "next" at - line 6.
うーんだめかー。
もはや理解もしないで手当たり次第にやってることがもろばれだ…。
まあ結論としては、packageでカレントパッケージを切り替えろ、ということでしょうかね。