我浏览了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]);
}
}
Run Code Online (Sandbox Code Playgroud)
在这里我想了解一下当我使用 foreach 时的情况,如下所示。
myIterator类的方法如何自动调用?
$it = new myIterator;
foreach($it as $key => $value) {
var_dump($key, $value);
echo "\n";
}
Run Code Online (Sandbox Code Playgroud)
这里有什么魔力?
如果您想这样称呼它,那么“神奇”就是当您尝试使用实现该Iterator接口的对象进行迭代时,PHP 具有已定义的行为。
您可能知道,接口只是程序员和应用程序之间的契约,规定将定义某些方法。如果定义类时没有实现接口中的方法,PHP 将抛出致命错误,并且程序将终止。这意味着当遇到foreach实现该接口的对象时Iterable,该对象保证具有名为current、key、next和rewind的方法valid。
除了 valid 之外,这些方法也适用于普通数组,尽管是过程函数而不是对象方法。(valid数组不存在,因为选择新项目的函数将返回该项目,因此您可以说它valid已融入这些函数中。)这表明,在幕后,foreach循环的工作方式或多或少相同在数组和Iterable对象上。
您在问题中链接的手册页的Iterable示例中显示了或至少暗示了迭代对象的过程,但我可以看到它可能会令人困惑。以下是该过程的基本解释:
一般来说,foreach循环会将可迭代对象的指针(注意这里的小 I - 我指的是实现接口的数组或对象Iterable)重置回其第一个位置。换句话说,它以与倒带磁带相同的方式“倒带”可迭代对象——年轻一代可能会忘记这个概念。正如您可能想象的那样,这是rewind该接口所需的方法。
一旦数组倒回,就会foreach尝试读取当前选择的任何元素。使用该方法检索当前元素的数据current,并使用该方法检索元素的键key。这些项目被放入您在循环中定义的变量中foreach,并且循环运行其迭代。
循环迭代完成后,foreach将尝试使用该方法获取下一个元素next。然后,它通过执行与上一段相同的步骤来处理循环。
在Iterable对象上,在使用currentand读取任何数据之前key,foreach循环将调用该valid方法。如果此方法返回FALSE或 PHP 认为与其等效的值(例如 0 或NULL),foreach则假定没有更多内容需要处理并完全退出循环,并且您的程序将照常继续。
| 归档时间: |
|
| 查看次数: |
1008 次 |
| 最近记录: |