recursiveIteratorIteratorでinner iteratorのメソッドが呼べるのはなぜ?
以前のエントリ id:balibali:20080518:1211129576 でオーバーライドがどうとか言っていた件ですが、いまだよくわからず、もうちょっとシンプルなサンプルコードを書いてみました。
<?php class Sample extends recursiveArrayIterator { function test() { echo 'This is a test.' . "\n"; } } $iterator = new recursiveIteratorIterator(new Sample()); $iterator->test();
で実行結果が、
$ php -f sample.php
This is a test.
Sample::test() はどうやって呼ばれているのでしょう??
リフレクション使って中身確認。
<?php ... ReflectionObject::export($iterator);
Object of class [ <internal:SPL> <iterateable> class RecursiveIteratorIterator implements Iterator, Traversable, OuterIterator ] { - Constants [4] { Constant [ integer LEAVES_ONLY ] { 0 } Constant [ integer SELF_FIRST ] { 1 } Constant [ integer CHILD_FIRST ] { 2 } Constant [ integer CATCH_GET_CHILD ] { 16 } } - Static properties [0] { } - Static methods [0] { } - Properties [0] { } - Dynamic properties [0] { } - Methods [18] { Method [ <internal:SPL, ctor> public method __construct ] { - Parameters [3] { Parameter #0 [ <required> Traversable $iterator ] Parameter #1 [ <optional> $mode ] Parameter #2 [ <optional> $flags ] } } Method [ <internal:SPL, prototype Iterator> public method rewind ] { } Method [ <internal:SPL, prototype Iterator> public method valid ] { } Method [ <internal:SPL, prototype Iterator> public method key ] { } Method [ <internal:SPL, prototype Iterator> public method current ] { } Method [ <internal:SPL, prototype Iterator> public method next ] { } Method [ <internal:SPL> public method getDepth ] { } Method [ <internal:SPL> public method getSubIterator ] { - Parameters [1] { Parameter #0 [ <optional> $level ] } } Method [ <internal:SPL, prototype OuterIterator> public method getInnerIterator ] { } Method [ <internal:SPL> public method beginIteration ] { } Method [ <internal:SPL> public method endIteration ] { } Method [ <internal:SPL> public method callHasChildren ] { } Method [ <internal:SPL> public method callGetChildren ] { } Method [ <internal:SPL> public method beginChildren ] { } Method [ <internal:SPL> public method endChildren ] { } Method [ <internal:SPL> public method nextElement ] { } Method [ <internal:SPL> public method setMaxDepth ] { - Parameters [1] { Parameter #0 [ <optional> $max_depth ] } } Method [ <internal:SPL> public method getMaxDepth ] { } } }
このリストには、test() というメソッドはない。
マジックメソッドの __call()*1 とか定義してあるなら話は早いのですが、それもなさげ。
んーんーーんーーーということで悩み中です。