NEXTとSUPERの挙動について
(昨日の続き)
NEXTを試してたら頭が混乱してきた - libnitsuji.so
で試してわかったこと。SUPERとの対比で。
クラス階層がこうなっていて、
A / E C ? / D
(?は本当はバックスラッシュです。なぜかはてなになるんだよな)
Dを基点にメソッドをコールしてクラス階層をさかのぼっていくと、
- SUPERの場合
- D -> E -> Aとさかのぼり、Aには親クラスがないのでそこで探索を終了(さらにエラー(Can't locate object method...)が発生する)
- NEXTの場合
- D -> E -> Aとさかのぼり、さらにA -> Cとさかのぼる。AとCには親クラスがないがエラーにはならない
で、このことはちゃんとDESCRIPTIONで説明されている。
If a method m calls $self-NEXT::m()>, the call to m is redispatched as if the calling method had not originally been found.
mというメソッドで$self->NEXT::m()をコールすると、あたかも(いま呼び出し中の)mというメソッドがなかったかのようにメソッドのディスパッチをし直します。
SUPERはその呼び出し時点での$selfの祖先をさかのぼるだけなので、Dのように複数の親クラスを持っている場合には1つの枝しかたどれないんですね。
一方のNEXTはもともとのクラスに戻って(いま呼び出したメソッドを見えなくしてから)呼び出しをやり直すので、すべての親クラスをたどれると。
なるほど。
Note that this is not the same thing as $self-SUPER::m()>, which begins a new dispatch that is restricted to searching the ancestors of the current class. $self-NEXT::m()> can backtrack past the current class -- to look for a suitable method in other ancestors of $self -- whereas $self-SUPER::m()> cannot.
これはそういう意味だったんだ。
さらにメソッドが見つからなかった場合にも(SUPERとは違って)エラーにはしないよ。たんになにもしないだけだよ。ということも書いてあります。
他にもいろいろ書いてあるんだけど、まあそれはまたの機会にでも。
あと、NEXTの話題はPerl Best PracticesのP389(Cumulative Methods)にもちょろっと出てきます。
-
- -
NEXT - Provide a pseudo-class NEXT (et al) that allows method redispatch - metacpan.org