我浏览了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";
}
这里的魔力是什么?
答案 0 :(得分:1)
如果您想要调用它,那么“魔术”就是当您尝试使用实现Iterator
接口的对象进行迭代时,PHP具有已定义的行为。
正如您所知,接口只是程序员和应用程序之间的契约,它表示将定义某些方法。如果在未实现接口中的方法的情况下定义了类,则PHP将抛出致命错误,程序将终止。这意味着当foreach
遇到实现Iterable
接口的对象时,该对象保证具有名为current
,key
,next
,{的方法。 {1}}和rewind
。
除了有效之外,这些都是普通数组所存在的方法,尽管是程序函数而不是对象方法。 (valid
对于数组不存在,因为选择新项目的函数将返回该项目,因此您可以说valid
被烘焙到这些函数中。)这表明,在引擎盖下, valid
循环在数组和foreach
对象上的工作方式大致相同。
在您问题中链接的manual page示例中,显示或至少暗示了迭代Iterable
对象的过程,但我可以看到它可能会让人感到困惑。以下是该过程的基本解释:
通常,Iterable
循环将重置指针的迭代(注意我在这里的小 - 我指的是实现foreach
接口的数组或对象)返回它的第一个位置。换句话说,它以与倒带的相同方式“倒带”迭代 - 这一概念可能会在年轻一代中丢失。正如您可能想象的那样,这是接口所需的Iterable
方法。
数据重绕后,rewind
会尝试读取当前选中的任何元素。使用foreach
方法检索当前元素的数据,并使用current
方法检索元素的键。这些项放在您在key
循环中定义的变量中,循环运行其迭代。
循环迭代完成后,foreach
将尝试使用foreach
方法获取下一个元素。然后通过执行与上一段相同的步骤来处理循环。
在next
对象上,在使用Iterable
和current
阅读任何数据之前,key
循环将调用foreach
方法。如果此方法返回valid
,或者PHP认为与其等效的值(例如0或FALSE
),则NULL
假设没有更多要处理并完全退出循环,并且程序继续正常进行。
答案 1 :(得分:0)
没有魔力。 foreach
将只检查一个对象是否实现了Iterator接口,然后按正确的顺序调用适当的方法。
您可以在此处找到更多详细信息:http://lxr.php.net/xref/PHP_5_4/Zend/zend_interfaces.c