3

我浏览了迭代器并了解了为什么应该使用它,但我没有得到的是迭代器类的方法如何调用通过 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";
}

这里有什么魔力?

4

2 回答 2

1

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

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

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

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

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

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

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

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

于 2013-01-05T13:18:22.743 回答
0

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

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

于 2013-01-05T13:00:41.373 回答