预定义接口(Predefined Interfaces)

  1. Traversable

  2. Iterator

  3. IteratorAggregate(聚合式迭代器)接口

  4. Generator 生成器

  5. ArrayAccess

  6. Serializable

  7. Closure

IteratorAggregate(聚合式迭代器)接口

接口摘要

IteratorAggregate extends Traversable {
/* 方法 */
abstract public Traversable getIterator ( void )
}

个接口实现了一个功能——创建外部迭代器,具体怎么理解呢,当我们使用foreach对对象进行便遍历的时候,如果没有继承IteratorAggregate接口,遍历的是对象中所有的public属性(只能是public $var这种形式)。要是继承了IteratorAggregate,会使用类中实现的getIterator方法返回的对象,这里要注意返回的一定要是一个Traversable对象或者扩展自Traversable的对象,否则会抛出异常

示例:

ArrayIterator 对数组进行了Iterator封装

class My{
 private $_data = [
 'a' => '燕睿涛',
 'b' => 'yanruitao',
 'c' => 'LULU',
 ];

 public function getIterator()
 {
   return new ArrayIterator($this->_data);
 }
}
$obj = new My;
foreach ($obj as $key => $value) {
 echo "$key => $value\n";
}
//输出结果为空

改造

结果:

示例:

Countable 的目的是能够使用php count函数来统计日志的行数

Iterator 迭代器需要实现current() key() next() rewind() valid()方法

foreach 之前,先rewind() ,将遍历的指针重置到遍历的开头,调用next() 将指针移动到下一个位置,current() 则可以获得当前指针指向数据,每次循环都会调用valid()方法,如果返回false,则证明遍历结束

a.log

思考:为什么不用 file() 函数读到数组里面再遍历?

有可能会出现一下错误(内存不够用):

解决办法:

用生成器!

生成器(Generator)

  • 生成器提供了一种更简单的可实现 Iterator 同样功能的方法。

  • 你可以通过生成器逐条产生(yield)供 foreach 遍历的数据,而且不需要事先在内存中建立整个数组。

  • 生成器像一个函数,但是使用关键词 yield 返回数据。

Generator 是 Traversable 的子类

示例:

进一步key=>value形式

IteratorAggregate 与 yield 的结合示例

getIterator 需要返回一个Traversable 对象, 生成器yield 就是一个Traversable的对象的子类

总结

  • 实现了 Traversable 的对象都可以通过 foreach 实现遍历;

  • 生成器函数实现 foreach 更简单,适用于简单的数据和逻辑;

  • Iterator 实现 foreach 可定制性更高,适用于较复杂的逻辑;

  • IteratorAggregate 可返回一个外部迭代器,可对数据本身及相关逻辑做更统一的封装。

资料

PHP之预定义接口详解

Last updated

Was this helpful?