php迭代器:Iterator和IteratorAggregate

使用迭代模式遍历所有的对象的时候,都必须实现Traversable(遍历)接口。但是Traversable是一个内部的类,只有用c语言编写的类才可以实现Traversable实现。如果我们在自定义的 类中实现它,会报错。那么我们要实现对象的遍历,就必须通过Iterator或者IteratorAggregate接口实现Traversable接口。

一,首先说说Iterator接口

它是在c语言中定义的,都是抽象方法,所以我们在实现接口的时候,就必须定义这些方法,代码如下:

Iterator extends Traversable {
    /* 方法 */
    abstract public mixed current ( void )
    abstract public scalar key ( void )
    abstract public void next ( void )
    abstract public void rewind ( void )
    abstract public boolean valid ( void )
}

接着我们在PHP中实现接口Iterator,代码如下:

//自定义类实现接口Iterator
class myIterator implements Iterator {
    private $position = 0;
    private $array = array(
        "firstelement",
        "secondelement",
        "lastelement",
    );  
 
    public function __construct() {
        $this->position = 0;
    }
    //定义rewind()-将数组指针移动到数组的开头位置
    function rewind() {
        var_dump(__METHOD__);
        $this->position = 0;
    }
    //定义current()-返回当前的值
    function current() {
        var_dump(__METHOD__);
        return $this->array[$this->position];
    }
    //定义可以key()-返回当前的键值
    function key() {
        var_dump(__METHOD__);
        return $this->position;
    }
    //定义next()-将数组指针向前进一位指向下一个数组元素
    function next() {
        var_dump(__METHOD__);
        ++$this->position;
    }
    //定义valid()-确定当前元素是否存在,并且必须在next()和rewind()方法之后才可以调用
    function valid() {
        var_dump(__METHOD__);
        return isset($this->array[$this->position]);
    }
}
 
$it = new myIterator;
 
foreach($it as $key => $value) {
    var_dump($key, $value);
    echo "
";
}

代码运行结果如下:

大家可能不明白,为什么利用foreach()就可以循环打印出类的属性,程序执行的顺序看我的注释,再次提醒大家注意
“定义valid()-确定当前元素是否存在,并且必须在next()和rewind()方法之后才可以调用”。


string(18) "myIterator::rewind" ----------程序开始执行首先调用rewind()函数,将数组指针移到数组开头位置
string(17) "myIterator::valid" ----------接着调用valid()当前元素是否存在,这个函数每次紧跟rewind()和next()函数被调用
string(19) "myIterator::current" ----------调用current()获取当前的值
string(15) "myIterator::key" ----------调用key()获取当前位置的键值
int(0)
string(12) "firstelement"

string(16) "myIterator::next" ----------上一步获取当前位置,肯定要调用next(),获取下一个位置的指针,即指针向下移动
string(17) "myIterator::valid" ----------判断当前元素是否存在
string(19) "myIterator::current" ----------如果存在,获取当前元素
string(15) "myIterator::key" ----------获取当前键值,为了下一步指针向前移动
int(1)
string(13) "secondelement"

string(16) "myIterator::next" ---------指针指向下一个元素
string(17) "myIterator::valid" ---------判断当前元素是否存在
string(19) "myIterator::current" ---------元素存在,获取当前的元素
string(15) "myIterator::key" ---------获取当前键值
int(2)
string(11) "lastelement"

string(16) "myIterator::next" ---------指针指向下一个位置
string(17) "myIterator::valid" ---------判断当前位置是否有值。如果有获取值,没有就结束遍历

二 ,IteratorAggregate接口

是用来将Iterator接口要求实现的5个方法委托给其他类(比如ArrayIterator)来实现


(1) ArrayIterator接口:允许从PHP数组中创建一个迭代器。上面我们通过实现Iterator接口实现迭代器,但是ArrayIterator可以直接跳过,实现同样的功能。

(2)当ArrayIterator迭代器和IteratorAggregate类一起使用的时候,直接免去Iterator创建方法的工作,所以在实现IteratorAggregate类中的方法getIterator时候,返回一个ArrayIterator接口就好。

(3) IteratorAggregate的c语言实现代码:定义抽象方法getIterator,所以实现接口的时候,必须定义该方法

IteratorAggregate extends Traversable { 
         /* 方法 */
    abstract public Traversable getIterator ( void )
}
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";
    }
    //定义方法----getIterator()---返回一个Iterator类的实例
    public function getIterator() {
        //ArrayIterator()接口可以创建一个Iterator实例
        return new ArrayIterator($this);
    }
}
 
$obj = new myData();
 
foreach($obj as $key => $value) {
    var_dump($key, $value);
    echo "
";
}

运行如下:
string(9) "property1"
string(19) "Public property one"

string(9) "property2"
string(19) "Public property two"

string(9) "property3"
string(21) "Public property three"

string(9) "property4"
string(13) "last property"

 

原文地址:https://www.cnblogs.com/tkzc2013/p/10574399.html