PHP Iterable接口

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类可以很容易地实现这个接口,也可以承载各种数据类型,而且代码简明易懂。

后端开发标签