Traversable遍历接口
在介绍Iterator之前,不得不介绍PHP的另外一个用于遍历的预定义接口Traversable。
Traversable接口是PHP内部的迭代器的抽象基类,只用于内部使用。一般我们用它来检测一个类是否可以使用foreach进行遍历。
上面的例子输出为:
需要注意到,虽然array没有继承Traversable,但是它仍然可以使用foreach遍历,所以我们一般使用下面的方法检测一个变量是否能够用foreach遍历:
Iterator迭代器接口
定义
Iterator是PHP预定义的可在内部迭代自己的外部迭代器或类的接口。实现该接口的类,可以使用foreach进行遍历,该接口在内部是继承自上面介绍的Traversable接口。
Iterator接口的定义如下:
实现Iterator接口并且实现上面定义的5个遍历基本方法,它们分别控制着foreach遍历时的行为。
实现方法
下面展示如何实现Iterator接口,从而能够让foreach正确遍历自定义类:
以上例子输出结果为:
显然foreach中各个方法调用的顺序如下:
首次调用rewind方法获得开始的键
调用valid方法查看当前索引是否有效
调用current方法获得当前的元素
调用key方法获得当前元素的键,如果foreach中没有使用key=>value的形式,则不会调用该方法
重复上面的过程,知道valid方法返回false,键无效则结束
IteratorAggregate聚合式迭代器接口
定义
你可能会对上面的Iterator是PHP预定义的可在内部迭代自己的外部迭代器或类的接口疑惑,其实迭代器分为可在内部迭代和不可内部迭代,换种说法,可在内部迭代相当于可以在内部自定义实现,反之则不然。
IteratorAggregate接口创建外部迭代器的接口,仅仅只是返回一个外部迭代器实例,实现该接口并不能像Iterator自定义迭代行为。它的定义如下:
显然,该接口只能返回一个迭代器实例,并不能像Iterator那样自定义迭代行为,如定义迭代元素等。
使用方法
上面实例的输出结果如下:
可见返回一个ArrayIterator实例,就相当于把类的属性当成了一个数组。
其中ArrayIterator是PHP内部定义的迭代器,是一个数组迭代器,还记得上面的Iterator接口的那个实例吗?我们可以改一下使得它更简单:
上面的类UIAIterator和UIterator的效果是一样的,都能够用foreach正确遍历类内部的data数组。而且UIAIterator更加简单。
当然,在实现IteratorAggregate接口的时候,除了可以返回ArrayIterator迭代器,还可以返回其他的PHP内部迭代器,比如SPL系列迭代器,甚至自定义迭代器。