SPL规定,所有实现了Iterator接口的class,都可以用在foreach Loop中。Iterator接口中包含5个必须实现的方法:
interface Iterator extends Traversable{
//返回当前元素
public mixed current ( void );
//返回当前元素的键
public scalar key ( void );
//向前移动到下一个元素
public void next ( void );
//返回到迭代器的第一个元素
public void rewind ( void );
//检查当前位置是否有效
public boolean valid ( void );
}
示例:
class MyIterator implements Iterator
{
private $position = 0;
private $array = array(
"firstelement",
"secondelement",
"lastelement",
);
function rewind() {
var_dump(__METHOD__);
$this->position = 0;
}
function current() {
var_dump(__METHOD__);
return $this->array[$this->position];
}
function key() {
var_dump(__METHOD__);
return $this->position;
}
function next() {
var_dump(__METHOD__);
++$this->position;
}
function valid() {
var_dump(__METHOD__);
return isset($this->array[$this->position]);
}
}
$it = new MyIterator;
foreach($it as $key => $value) {
var_dump($key, $value);
echo "\n";
}
实现ArrayAccess接口,可以使得object像array那样操作。ArrayAccess接口包含四个必须实现的方法:
interface ArrayAccess {
//检查一个偏移位置是否存在
public mixed offsetExists ( mixed $offset );
//获取一个偏移位置的值
public mixed offsetGet( mixed $offset );
//设置一个偏移位置的值
public mixed offsetSet ( mixed $offset );
//复位一个偏移位置的值
public mixed offsetUnset ( mixed $offset );
}
class obj implements arrayaccess {
private $container = array();
public function __construct() {
$this->container = array(
"one" => 1,
"two" => 2,
"three" => 3,
);
}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->container[$offset]);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
}
public function offsetGet($offset) {
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
}
$obj = new obj;
var_dump($obj);exit;
var_dump(isset($obj["two"]));
var_dump($obj["two"]);
unset($obj["two"]);
var_dump(isset($obj["two"]));
$obj["two"] = "A value";
var_dump($obj["two"]);
$obj[] = ‘Append 1‘;
$obj[] = ‘Append 2‘;
$obj[] = ‘Append 3‘;
print_r($obj);
IteratorAggregate 聚合式迭代器接口
假设对象A实现了上面的ArrayAccess接口,这时候虽然可以像数组那样操作,却无法使用foreach遍历,除非实现了前面提到的Iterator接口。
另一个解决方法是,有时会需要将数据和遍历部分分开,这时就可以实现IteratorAggregate接口。它规定了一个getIterator()
方法,返回一个使用Iterator接口的object。
IteratorAggregate extends Traversable {
/* 获取一个外部迭代器 */
abstract public Traversable getIterator ( void )
}
示例:
<?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";
}
?>
注意:
虽然都继承自Traversable
,但这是一个无法在 PHP 脚本中实现的内部引擎接口。我们直接使用IteratorAggregate
或 Iterator
接口来代替它。
这个接口用于遍历多层数据,它继承了Iterator接口,因而也具有标准的current()、key()、next()、 rewind()和valid()方法。同时,它自己还规定了getChildren()
和hasChildren()
方法。The getChildren()
method must return an object that implements RecursiveIterator。
SeekableIterator接口也是Iterator接口的延伸,除了Iterator的5个方法以外,还规定了seek()
方法,参数是元素的位置,返回该元素。如果该位置不存在,则抛出OutOfBoundsException。
这个接口规定了一个count()
方法,返回结果集的数量。
<?php
//Example One, BAD
class CountMe
{
protected $_myCount = 3;
public function count()
{
return $this->_myCount;
}
}
$countable = new CountMe();
echo count($countable); //result is "1", not as expected
echo $countable->count;//result is "3"
//Example Two, GOOD
class CountMe implements Countable
{
protected $_myCount = 3;
public function count()
{
return $this->_myCount;
}
}
$countable = new CountMe();
echo $countable->count();//result is "3"
echo count($countable); //result is "3" as expected
?>
OuterIterator 迭代器接口
<?php
/**
*
*/
class outerImpl extends IteratorIterator
{
public function current()
{
# code...
return parent::current().‘_tail‘;
}
public function key()
{
return ‘pre_‘.parent::key();
}
}
$array = [‘value1‘,‘value2‘,‘value3‘,‘value4‘];
$outerObj = new outerImpl(new ArrayIterator($array));
foreach ($outerObj as $key => $value) {
# code...
echo ‘++‘.$key.‘-‘.$value.PHP_EOL;
}
原文:https://www.cnblogs.com/xiaobingch/p/12464529.html