Сравнение генераторов с объектами класса Iterator

Главное преимущество генераторов — простота. Требуется написать гораздо меньше шаблонного кода по сравнению с реализацией объекта класса Iterator, и этот код гораздо более простой и понятный. Например, эта функция и класс делают одно и то же.

<?php

function getLinesFromFile($fileName)
{
if (!
$fileHandle = fopen($fileName, 'r')) {
return;
}

while (
false !== $line = fgets($fileHandle)) {
yield
$line;
}

fclose($fileHandle);
}

// Против...

class LineIterator implements Iterator
{
protected
$fileHandle;

protected
$line;
protected
$i;

public function
__construct($fileName)
{
if (!
$this->fileHandle = fopen($fileName, 'r')) {
throw new
RuntimeException('Невозможно открыть файл "' . $fileName . '"');
}
}

public function
rewind()
{
fseek($this->fileHandle, 0);
$this->line = fgets($this->fileHandle);
$this->i = 0;
}

public function
valid()
{
return
false !== $this->line;
}

public function
current()
{
return
$this->line;
}

public function
key()
{
return
$this->i;
}

public function
next()
{
if (
false !== $this->line) {
$this->line = fgets($this->fileHandle);
$this->i++;
}
}

public function
__destruct()
{
fclose($this->fileHandle);
}
}

?>

Однако за эту гибкость приходится платить: генераторы — однонаправленные итераторы и их нельзя перемотать после начала итерации. Это также означает, что один и тот же генератор нельзя повторять несколько раз: генератор необходимо пересоздавать каждый раз, снова вызвав функцию генератора.

Смотрите также