1. 什么是Iterable接口?
在PHP 7.1中,引入了一个新的接口:Iterable。这个接口的作用是验证一个对象是否可以被迭代。实现这个接口需要定义一个方法:getIterator(),返回一个Iterator对象。
interface Iterable {
public function getIterator(): Iterator;
}
这个接口在PHP内置了一个特殊的语法结构:foreach循环结构。
foreach ($iterator as $value) {
// 处理$value
}
在使用foreach循环时,系统会调用Iterator对象中的 rewind()、valid()、current() 和 next() 四个方法。如果对象实现了可迭代接口,那么foreach循环中的 $iterator 就是调用对象的getIterator()方法的返回值。
2. Iterator接口和实现
2.1 Iterator接口
PHP中的Iterator接口是一个单独的接口,定义了四个核心的方法,实现这些方法能够让对象变得可迭代。这四个方法分别是:
rewind():重置指针,将指针指向迭代器的第一个元素。
next():向前移动指针到下一个元素。
current():返回当前的元素。
valid():检查迭代器是否已经遍历完。
interface Iterator {
public function rewind(): void;
public function next(): void;
public function current();
public function key();
public function valid(): bool;
}
2.2 实现Iterator接口
实现 Iterator 接口需要定义上述四个方法,其中current()方法返回当前指针所在位置的元素,key()方法返回当前元素的键。
下面是一个简单的示例代码:
class MyList implements Iterator {
private $idx = 0;
private $list = array(1, 2, 3, 4, 5, 6);
public function rewind(): void {
$this->idx = 0;
}
public function current() {
return $this->list[$this->idx];
}
public function key(): int {
return $this->idx;
}
public function next(): void {
++$this->idx;
}
public function valid(): bool {
return isset($this->list[$this->idx]);
}
}
$list = new MyList();
foreach ($list as $key => $value) {
echo $key . ' => ' . $value . '
';
}
以上代码输出:
0 => 1
1 => 2
2 => 3
3 => 4
4 => 5
5 => 6
这说明我们已经实现了Iterator接口,可以使用foreach结构进行循环操作。
3. 实现Iterable接口
3.1 实现实例化方法
实例化类需要提供一个可迭代的集合,可以使用array来提供。在实现Iterable接口后,创建一个MyCollection类,包含了一个构造方法,可以接收一个可迭代结构(此处传入的是一个数组),将数据保存在私有属性中。
class MyCollection implements IteratorAggregate {
private $items = array();
public function __construct(array $items) {
$this->items = $items;
}
}
3.2 实现getIterator()方法
实现Iterable接口需要实现getIterator()方法,返回一个Iterator对象,可以在MyCollection中实现getIterator()方法返回一个ArrayIterator迭代器对象,该对象可以迭代数组。
class MyCollection implements IteratorAggregate {
private $items = array();
public function __construct(array $items) {
$this->items = $items;
}
public function getIterator(): Iterator {
return new ArrayIterator($this->items);
}
}
以上代码中,getIterator()方法返回了一个ArrayIterator对象,该对象将items数组变得可迭代。
4. 测试可迭代性
现在,我们已经定义了一个可迭代对象,可以进行foreach循环,我们来验证一下:
$collection = new MyCollection(array(1, 2, 3, 4, 5));
foreach ($collection as $key => $value) {
echo "{$key} => {$value}
";
}
以上代码输出:
0 => 1
1 => 2
2 => 3
3 => 4
4 => 5
这告诉我们,我们已经实现了可迭代接口。
5. 结论
Iterable接口是一个很有用的功能,可以使您的代码实现foreach循环的功能,而无需在每个类中都实现Iterator接口。MyCollection类可以很容易地实现这个接口,也可以承载各种数据类型,而且代码简明易懂。