SPL基础接口
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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)