6.10.9 实现迭代器和迭代
PHP的面向对象引擎提供了一个非常聪明的特性,也就是,可以使用foreach()方法通过循环方式取出一个对象的所有属性,就像数组方式一样。如下例所示:
class myClass
{
public$a="5";
public$b="7";
public$c="9";
}
$x=new myClass;
foreach($x as$attribute){
echo$attribute."<br/>";
}
(在本书编写的时候,PHP手册建议必须对foreach接口实现一个空的Traversable接口,但是这样做将导致一个致命错误。然而,不实现这个接口却能正常工作)。
如果需要一些更加复杂的行为,可以实现一个iterator(迭代器)。要实现一个迭代器,必须将要迭代的类实现IteratorAggregate接口,并且定义一个能够返回该迭代类实例的getIterator方法。这个类必须实现Iterator接口,该接口提供了一系列必须实现的方法。
迭代器和迭代的示例如程序清单6-4所示。
程序清单6-4 迭代器和迭代的示例基类
<?php
class ObjectIterator implements Iterator{
private$obj;
private$count;
private$currentIndex;
function__construct($obj)
{
$this->obj=$obj;
$this->count=count($this->obj->data);
}
function rewind()
{
$this->currentIndex=0;
}
function valid()
{
return$this->currentIndex<$this->count;
}
function key()
{
return$this->currentIndex;
}
function current()
{
return$this->obj->data[$this->currentIndex];
}
function next()
{
$this->currentIndex++;
}
}
class Object implements IteratorAggregate
{
public$data=array();
function__construct($in)
{
$this->data=$in;
}
function getIterator()
{
return new ObjectIterator($this);
}
}
$myObject=new Object(array(2,4,6,8,10));
$myIterator=$myObject->getIterator();
for($myIterator->rewind();$myIterator->valid();$myIterator->next())
{
$key=$myIterator->key();
$value=$myIterator->current();
echo$key."=>".$value."<br/>";}
?>
ObjectIterator类具有Iterator接口所要求的一系列函数:
■构造函数并不是必需的,但是很明显,它是设置将要迭代的项数和当前数据项链接的地方。
■rewind()函数将内部数据指针设置回数据开始处。
■valid()函数将判断数据指针的当前位置是否还存在更多数据。
■key()函数将返回数据指针的值。
■value()函数将返回保存在当前数据指针的值。
■next()函数在数据中移动数据指针的位置。
像这样使用Iterator类的原因就是即使潜在的实现发生了变化,数据的接口还是不会发生变化。在下一章中,IteratorAggregate类是一个简单的数组。如果要将其换成散列(hash)表或链接列表,虽然Iterator代码可能发生变化,但是还可以使用标准的Iterator来遍历它。