原文地址:这里写链接内容
本文是在看symfony框架的http-foundation组件的parameterBag查阅的,于原文有一定的修改。
实现Iterator接口
<?php
class MyIterator implements Iterator{
private $_d = array('a','b','c','d');
private $_p = 0;
public function __construct(){
$this->_p = 0;
}
/**
* 返回当前值
*
* @see Iterator::current()
*/
public function current() {
var_dump(__METHOD__);
return $this->_d[$this->_p];
}
/**
* 当前索引加1
*
*
* @see Iterator::next()
*/
public function next() {
var_dump(__METHOD__);
$this->_p++;
}
/**
* 返回当前索引值
*
*
* @see Iterator::key()
*/
public function key() {
var_dump(__METHOD__);
return $this->_p;
}
/**
* 对当前值进行验证
*
* @see Iterator::valid()
*/
public function valid() {
var_dump(__METHOD__);
return isset($this->_d[$this->_p]);
}
/**
* 将数组索引置为0
*
*
* @see Iterator::rewind()
*/
public function rewind() {
var_dump(__METHOD__);
$this->_p = 0;
}
}
$me = new MyIterator();
foreach($me as $key => $value){
//var_dump($key) . ':' . var_dump($value);
var_dump('.......start...........', $key, $value,'.......end...........');
}
输出结果:
string 'MyIterator::rewind' (length=18)
string 'MyIterator::valid' (length=17)
string 'MyIterator::current' (length=19)
string 'MyIterator::key' (length=15)
string '.......start...........' (length=23)
int 0
string 'a' (length=1)
string '.......end...........' (length=21)
string 'MyIterator::next' (length=16)
string 'MyIterator::valid' (length=17)
string 'MyIterator::current' (length=19)
string 'MyIterator::key' (length=15)
string '.......start...........' (length=23)
int 1
string 'b' (length=1)
string '.......end...........' (length=21)
string 'MyIterator::next' (length=16)
string 'MyIterator::valid' (length=17)
string 'MyIterator::current' (length=19)
string 'MyIterator::key' (length=15)
string '.......start...........' (length=23)
int 2
string 'c' (length=1)
string '.......end...........' (length=21)
string 'MyIterator::next' (length=16)
string 'MyIterator::valid' (length=17)
string 'MyIterator::current' (length=19)
string 'MyIterator::key' (length=15)
string '.......start...........' (length=23)
int 3
string 'd' (length=1)
string '.......end...........' (length=21)
string 'MyIterator::next' (length=16)
string 'MyIterator::valid' (length=17)
让我们分析一下:
1、在循环刚开始的时候,将对象中数组的索引置为0,并检查当前索引是否有值.
2、索引加一。
3、验证该索引下是否有值。
4、如果有、返回值。
5、返回索引值。
6、重复2、3、4、步奏。如果验证某索引下没有值,就此中断。
缺点:
1、我们需要实现这么多的函数(5个)。
2、上面说到,如果某一索引下没有值,则就此中断了,不在循环,如果我们的数组是这样的private $_d = array(‘a’,’b’,’c’,’d’,8 => ‘f’);。那么f值就不会被输出。
我们先来解决第一个缺点。
实现子接口IteratorAggregate
<?php
class myData implements IteratorAggregate {
public $property1 = "Public property one";
public $property2 = "Public property two";
public $property3 = "Public property three";
public function __construct() {
$this->property4 = "last property";
}
public function getIterator() {
return new ArrayIterator($this);
}
}
$obj = new myData;
foreach($obj as $key => $value) {
var_dump($key, $value);
echo "\n";
}
输出结果:
string 'property1' (length=9)
string 'Public property one' (length=19)
string 'property2' (length=9)
string 'Public property two' (length=19)
string 'property3' (length=9)
string 'Public property three' (length=21)
string 'property4' (length=9)
string 'last property' (length=13)
我们只需实现一个方法getIterator就OK了。是不是简单了。我们也可以直接实现MyIterator ,看看出现什么样的结果,自己去尝试下吧。
解决第二个缺点,这就需要我们来完善MyIterator,保证当索引不连续时,也能输出后面的值。封装的思想啊,大家尝试下吧。
下面再说一说Traversable接口,这个接口中什么样的抽样方法都没有,他是Iterator的父接口。最底层的,这个接口一般不会去实现它,如果非得要实现它,记住两点。
1、必须和Iterator、IteratorAggregate两个接口中的某一个或者两个一起用。
2、IteratorAggregate或者Iterator必须放在Traversable前面。如:class MyIterator implements Iterator,Traversable{}。切记。