【问题标题】:How the Iterator methods are called upon iterating object through foreach通过 foreach 迭代对象时如何调用 Iterator 方法
【发布时间】:2013-01-05 12:47:23
【问题描述】:

我浏览了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";
}

这里有什么魔力?

【问题讨论】:

    标签: php iterator


    【解决方案1】:

    如果你想这么称呼它,“魔法”就是当你尝试使用实现Iterator 接口的对象进行迭代时,PHP 具有定义的行为。

    您可能知道,接口只是程序员和应用程序之间的合同,规定将定义某些方法。如果定义了一个类而没有实现接口中的方法,PHP 将抛出一个致命错误,程序将终止。这意味着当foreach 遇到一个实现Iterable 接口的对象时,该对象保证具有称为currentkeynextrewindvalid 的方法。

    除了v​​alid之外,这些方法也都存在于普通数组中,尽管它们是过程函数而不是对象方法。 (valid 不存在于数组中,因为选择新项目的函数将返回该项目,因此您可以说 valid 已融入这些函数。)这表明,在幕后,foreach循环在数组和 Iterable 对象上的工作方式或多或少相同。

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

    一般来说,foreach 循环会将可迭代对象的指针(注意这里的小 I - 我指的是实现Iterable 接口的数组或对象)回到它的第一个位置。换句话说,它以与倒带磁带相同的方式“倒带”可迭代对象——年轻一代可能会忘记这一概念。可以想象,这就是接口需要的rewind 方法。

    一旦数组回绕,foreach 会尝试读取当前选择的任何元素。当前元素的数据使用current 方法检索,元素的键使用key 方法检索。这些项目被放入您在foreach 循环中定义的变量中,并且循环运行它的迭代。

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

    Iterable 对象上,在使用currentkey 读取任何数据之前,foreach 循环将调用valid 方法。如果此方法返回 FALSE,或 PHP 认为与它等效的值(如 0 或 NULL),foreach 假定没有更多内容需要处理并完全退出循环,您的程序将照常继续。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 2021-10-13
        • 1970-01-01
        • 2017-04-25
        • 2015-06-07
        • 1970-01-01
        • 1970-01-01
        • 2011-03-19
        • 2012-09-04
        • 2021-12-25
        相关资源
        最近更新 更多