Iterator 迭代器接口

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 数组式访问接口

实现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 接口来代替它。

RecursiveIterator

  • 可以对多层结构的迭代器进行迭代,比如遍历一棵树
  • 所有具有层次结构特点的数据都可以用这个接口遍历,如文件夹
  • 关键方法
    • hasChildren方法可以用于判断当前节点是否存在子节点
    • getChildren方法用于得到当前节点子节点的迭代器
  • SPL中实现该接口的类
  • RecursiveArrayIterator,RecuriveCachingIterator等以Recurive开头的类都可以进行多层次结构化遍历

这个接口用于遍历多层数据,它继承了Iterator接口,因而也具有标准的current()、key()、next()、 rewind()和valid()方法。同时,它自己还规定了getChildren()hasChildren()方法。The getChildren() method must return an object that implements RecursiveIterator。

SeekableIterator

  • SeekableIterator

    • 可以通过seek方法定位到集合里面的某个特定的元素
    • seek方法的参数是元素的位置,从0开始计算
  • SPL中实现该接口的类
    • ArrayIterator、DirectoryIterator、FilesystemIterator、GlobIterator、RecursiveArrayIterator、RecursiveDirectoryIterator

SeekableIterator接口也是Iterator接口的延伸,除了Iterator的5个方法以外,还规定了seek()方法,参数是元素的位置,返回该元素。如果该位置不存在,则抛出OutOfBoundsException。

Countable

这个接口规定了一个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 迭代器接口

  • OuterIterator如果想对迭代器进行一定的处理之后再返回,可以用这个接口
  • IteratorIterator类是OuterIterator的实现,扩展的时候可以直接继承IteratorIterator
<?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;
}

最新文章

  1. YbSoftwareFactory 代码生成插件【二十】:DynamicObject的序列化
  2. Getting Real 开发宝典
  3. PHP5: mysqli 插入, 查询, 更新和删除 Insert Update Delete Using mysqli (CRUD)
  4. 少睡与吸烟影响IQ
  5. NOIP201105铺地毯
  6. 翻译「C++ Rvalue References Explained」C++右值引用详解 Part4:强制Move语义
  7. spoj 694(后缀数组)
  8. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(42)-工作流设计01
  9. C#设计及其UML(反向工程)
  10. 具体的了解“&amp;gt;/dev/null 2&amp;gt;&amp;amp;1”
  11. [妙味DOM]第六课:鼠标滚轮和COOKIE
  12. js中原生对象、内置对象和宿主对象(转)
  13. vue2组件之select2调用
  14. 工作流Activiti5.13学习笔记(一)
  15. OpenMP与MPI联合编程
  16. Spring基础4
  17. java web(四):request、response一些用法和文件的上传和下载
  18. 斯坦福大学自然语言处理第四课“语言模型(Language Modeling)”
  19. poj 2406 Power Strings(kmp应用)
  20. oracle学习操作(1)

热门文章

  1. python 遍历, 获取目录下所有文件名和文件夹的方法-----os.walk(), os.listdir
  2. Linux笔记(shell基础,历史命令,命令补全/别名,通配符,输出重定向)
  3. R 语言命令行参数处理
  4. double运算的坑
  5. tomcat8调优
  6. C# 基础知识系列- 16 开发工具篇
  7. A - ACM Computer Factory POJ - 3436 网络流
  8. numpy数组的分割与合并
  9. Azure AD(二)调用受Microsoft 标识平台保护的 ASP.NET Core Web API 上
  10. Akko海洋之星