如何通过foreach迭代对象来调用Iterator方法

时间:2013-01-05 12:47:23

标签: php iterator

我浏览了Iterator,并了解了它应该被使用的原因,但我没有得到的是迭代器类的方法如何通过foreach迭代对象。

考虑从php手册页

复制的以下示例
class myIterator implements Iterator {
    private $position = 0;
    private $array = array(
        "firstelement",
        "secondelement",
        "lastelement",
    );  

    public function __construct() {
        $this->position = 0;
    }

    function rewind() {
        var_dump(__METHOD__);
        $this->position = 0;
    }

    function current() {
        var_dump(__METHOD__);
        return $this->array[$this->position];
    }

    function key() {
        var_dump(__METHOD__);
        return $this->position;
    }

    function next() {
        var_dump(__METHOD__);
        ++$this->position;
    }

    function valid() {
        var_dump(__METHOD__);
        return isset($this->array[$this->position]);
    }
}

在这里,我想了解当我使用foreach时如下。

如何自动调用myIterator类的方法?

$it = new myIterator;

foreach($it as $key => $value) {
    var_dump($key, $value);
    echo "\n";
}

这里的魔力是什么?

2 个答案:

答案 0 :(得分:1)

如果您想要调用它,那么“魔术”就是当您尝试使用实现Iterator接口的对象进行迭代时,PHP具有已定义的行为。

正如您所知,接口只是程序员和应用程序之间的契约,它表示将定义某些方法。如果在未实现接口中的方法的情况下定义了类,则PHP将抛出致命错误,程序将终止。这意味着当foreach遇到实现Iterable接口的对象时,该对象保证具有名为currentkeynext,{的方法。 {1}}和rewind

除了有效之外,这些都是普通数组所存在的方法,尽管是程序函数而不是对象方法。 (valid对于数组不存在,因为选择新项目的函数将返回该项目,因此您可以说valid被烘焙到这些函数中。)这表明,在引擎盖下, valid循环在数组和foreach对象上的工作方式大致相同。

在您问题中链接的manual page示例中,显示或至少暗示了迭代Iterable对象的过程,但我可以看到它可能会让人感到困惑。以下是该过程的基本解释:

通常,Iterable循环将重置指针的迭代(注意我在这里的小 - 我指的是实现foreach接口的数组或对象)返回它的第一个位置。换句话说,它以与倒带的相同方式“倒带”迭代 - 这一概念可能会在年轻一代中丢失。正如您可能想象的那样,这是接口所需的Iterable方法。

数据重绕后,rewind会尝试读取当前选中的任何元素。使用foreach方法检索当前元素的数据,并使用current方法检索元素的键。这些项放在您在key循环中定义的变量中,循环运行其迭代。

循环迭代完成后,foreach将尝试使用foreach方法获取下一个元素。然后通过执行与上一段相同的步骤来处理循环。

next对象上,在使用Iterablecurrent阅读任何数据之前,key循环将调用foreach方法。如果此方法返回valid,或者PHP认为与其等效的值(例如0或FALSE),则NULL假设没有更多要处理并完全退出循环,并且程序继续正常进行。

答案 1 :(得分:0)

没有魔力。 foreach将只检查一个对象是否实现了Iterator接口,然后按正确的顺序调用适当的方法。

您可以在此处找到更多详细信息:http://lxr.php.net/xref/PHP_5_4/Zend/zend_interfaces.c