SPL迭代器
《迭代器设计模式和
PHP》中必须论述“标准
PHP库”(SPL)迭代器
。虽然
,使用while循环结构可以非常紧凑
,并且也很有用,但是PHP代码或许更适合数组迭代的foreach结构
。直接在foreach循环中使用集合合适吗?这其实就是SPL迭代器的目标。(尽管本章整篇都是写PHP5,下列SPL代码只能在PHP5中运行,并且仅当在PHP5编译中将SPL启用。)
Fuecks写过一篇文章,详细地介绍了SPL和SPL迭代器;请参阅。使用SPL是一种完全不同的实现迭代的方法,因此首先介绍一个新单元测试例子和一个新的类ForeachableLibrary。
classSplIteratorTestCaseextendsUnitTestCase{
protected$lib;
functionsetup(){
$this->lib=newForeachableLibrary;
$this->lib->add(newMedia(‘name1’,2000));
$this->lib->add(newMedia(‘name2’,2002));
$this->lib->add(newMedia(‘name3’,2001));
}
functionTestForeach(){
$output=‘’;
foreach($this->libas$item){
$output.=$item->name;
}
$this->assertEqual(‘name1name2name3’,$output);
}
}
ForeachableLibrary是实现SPL迭代器接口的集合。你必须执行5个函数来创建SPL迭代器:current()、next()、key()、valid()和rewind()。key()返回集合的当前索引。rewind()类似于reset():在集合启动时重新启动迭代。
classForeachableLibrary
extendsLibraryimplementsIterator{
protected$valid;
functioncurrent(){
returncurrent($this->collection);
}
functionnext(){
$this->valid=(false!==next($this->collection));
}
functionkey(){
returnkey($this->collection);
}
functionvalid(){
return$this->valid;
}
functionrewind(){
$this->valid=(false!==reset($this->collection));
}
}
这里,该代码仅仅实现了处理$collection属性的必需的函数。(如果你没有实现所有5个函数,并且将实现迭代器添加到类definition,则PHP将出现致命错误。)测试尚不成熟,因此,什么都有可能发生。存在一个问题:事实受限于一种迭代类型-排序,或者fil-tering不可用。可以采取措施来调整这种情况?是的!应用从策略模式中学到的知识(请参阅第7章),将SPL迭代器的5个函数作为另一个对象的示例。这是关于PolymorphicForeachableLibrary的测试。
classPolySplIteratorTestCaseextendsUnitTestCase{
protected$lib;
functionsetup(){
$this->lib=newPolymorphicForeachableLibrary;
$this->lib->add(newMedia(‘name1’,2000));
$this->lib->add(newMedia(‘name2’,2002));
$this->lib->add(newMedia(‘name3’,2001));
}
functionTestForeach(){
$output=‘’;
foreach($this->libas$item){
$output.=$item->name;
}
$this->assertEqual(‘name1name2name3’,$output);
}
}
这种情况与SplIteratorTestCase测试的唯一差别在于$this->lib属性类是在setUp()方法中创建的。这意味着:这两个类的运行方式必须一致。PolymorphicForeachableLibrary:classPolymorphicForeachableLibrary扩展库
implementsIterator{
protected$iterator;
functioncurrent(){
return$this->iterator->current();
}
functionnext(){
return$this->iterator->next();
}
functionkey(){
return$this->iterator->key();
}
functionvalid(){
return$this->iterator->valid();
}
functionrewind(){
$this->iterator=
newStandardLibraryIterator($this->collection);
$this->iterator->rewind();
}
}
扩展库加入集合处理方法。并添加SPL方法,这些方法代表了$iterator属性,在rewind()中创建。以下是StandardLibraryIterator的代码。
classStandardLibraryIterator{
protected$valid;
protected$collection;
function__construct($collection){
$this->collection=$collection;
}
functioncurrent(){
returncurrent($this->collection);
}
functionnext(){
$this->valid=(false!==next($this->collection));
}
functionkey(){
returnkey($this->collection);
}
functionvalid(){
return$this->valid;
}
functionrewind(){
$this->valid=(false!==reset($this->collection));
}
}
该代码看起来很熟悉:实际上,这来自于5个SPL函数ForeachableLibrary类。