排序迭代器
迭代器不仅可以显示全部或部分集合
。而且
,还可以按特定顺序显示集合
。下面
,创建一个按集合众介质的发布日期进行排序的迭代器。为了进行测试,请添加某些日期在setUp()方法中添加的项之后的介质实例。如果迭代器运行,则这些日期较后的项应该位于迭代操作的最前面。
classIteratorTestCaseextendsUnitTestCase{
//...
functionTestReleasedIteratorUsage(){
$this->lib->add(newMedia(‘second’,1999));
$this->lib->add(newMedia(‘first’,1989));
$this->assertIsA(
$it=$this->lib->getIterator(‘released’)
,’LibraryReleasedIterator’);
$output=array();
while($item=$it->next()){
$output[]=$item->name.’-’.$item->year;
}
$this->assertEqual(
‘first-1989second-1999name1-2000name3-2001name2-2002’
,implode(‘‘,$output));
}
}
该测试使用的项在每个迭代中略有不同:并不仅仅是在字符串值后添加$name,而是,字符串同时具有$name和$year属性,这些属性随后将被添加到$output数组。LibraryReleasedIterator的实现与LibraryIterator非常类似,除了constuctor中的一行语句:
classLibraryReleasedIteratorextendsLibraryIterator{
function__construct($collection){
usort($collection,create_function(‘$a,$b’,’return($a->year-$b->year);’));
$this->collection=$collection;
}
}
用粗体表示的这一行将$collection数组排在迭代之前。你可以通过简单地继承LibraryIterator类,来避免复制该类的其它所有代码。可以使用外部迭代器来实现相同的排序迭代吗?是的,但是你必须注意完成它的诀窍。
classLibraryReleasedExternalIterator{
protected$collection;
protected$sorted_keys;
protected$key=-1;
function__construct($collection){
$this->collection=$collection;
$sort_funct=create_function(
‘$a,$b,$c=false’,
‘static$collection;
if($c){
$collection=$c;
return;
}
return($collection->get($a)->year-
$collection->get($b)->year);’);
$sort_funct(null,null,$this->collection);
$this->sorted_keys=$this->collection->keys();
usort($this->sorted_keys,$sort_funct);
}
functionnext(){
if(++$this->key>=$this->collection->count()){
returnfalse;
}else{
return$this->collection->get($this->sorted_keys[$this->key]);
}
}
}
其中,关键是创建用于排序的实用程序函数。排序函数必须能够访问集合,以便可以获取对照成员。然而,因为gener-ated函数在usort()中使用,没有将集合作为其它参数传递的选项。相反,你可以利用上述代码块中显示的诀窍,在利用usort()调用函数之前,将引用存储在函数中内部的集合中。排序的项是集合的关键字列表。当usort()完成时,关键字会按照集合中每个对象的year属性的顺序进行排序。在next()方法中,可以通过get()方法访问集合中的对象,而不是间接通过$sorted_keys映射。如果重新调用外部版本的GoF风格的迭代器,则不连续的数组或关键字中的字符串可能会有问题。可以使用针对sim-ple外部迭代器的相同诀窍,来减少关键字顺序不连贯的问题。