Поэтому я не уверен, является ли это ошибочным дизайном с PHP или есть понятная логика для обработки противоречивых результатов для одного и того же интерфейса.
Интерфейс SeekableIterator имеет два метода (seek
и valid
), которые либо конфликтуют друг с другом, либо должны работать последовательно друг с другом, но я вижу оба.
В документации к интерфейсу сказано, что seek
должно генерировать исключение класса OutOfBoundsException, но это, по-видимому, сводит на нет полезность valid
, если только позиция итератора не обновляется (заставляя valid
возвращать false) перед генерацией исключения (которое, по-видимому, должно быть перехвачено).
Три тестовых примера
Пример 1.
Пользовательский класс, реализующий SeekableIterator, как показано в примере в документах:
Класс:
class MySeekableIterator implements SeekableIterator {
private $position;
private $array = array(
"first element",
"second element",
"third element",
"fourth element"
);
/* Method required for SeekableIterator interface */
public function seek($position) {
if (!isset($this->array[$position])) {
throw new OutOfBoundsException("invalid seek position ($position)");
}
$this->position = $position;
}
/* Methods required for Iterator interface */
public function rewind() {
$this->position = 0;
}
public function current() {
return $this->array[$this->position];
}
public function key() {
return $this->position;
}
public function next() {
++$this->position;
}
public function valid() {
return isset($this->array[$this->position]);
}
}
Пример 1. Тест:
echo PHP_EOL . "Custom Seekable Iterator seek Test" . PHP_EOL;
$it = new MySeekableIterator;
$it->seek(1);
try {
$it->seek(10);
echo $it->key() . PHP_EOL;
echo "Is valid? " . (int) $it->valid() . PHP_EOL;
} catch (OutOfBoundsException $e) {
echo $e->getMessage() . PHP_EOL;
echo $it->key() . PHP_EOL; // outputs previous position (1)
echo "Is valid? " . (int) $it->valid() . PHP_EOL;
}
Выход теста 1:
Custom Seekable Iterator seek Test
invalid seek position (10)
1
Is valid? 1
Пример 2:
Использование родного ArrayIterator::seek
Тест 2 Код:
echo PHP_EOL . "Array Object Iterator seek Test" . PHP_EOL;
$array = array('1' => 'one',
'2' => 'two',
'3' => 'three');
$arrayobject = new ArrayObject($array);
$iterator = $arrayobject->getIterator();
$iterator->seek(1);
try {
$iterator->seek(5);
echo $iterator->key() . PHP_EOL;
echo "Is valid? " . (int) $iterator->valid() . PHP_EOL;
} catch (OutOfBoundsException $e) {
echo $e->getMessage() . PHP_EOL;
echo $iterator->key() . PHP_EOL; // outputs previous position (1)
echo "Is valid? " . (int) $iterator->valid() . PHP_EOL;
}
Выход теста 2:
Array Object Iterator seek Test
Seek position 5 is out of range
1
Is valid? 1
Пример 3:
Использование родного DirectoryIterator::seek
Тест 3 Код:
echo PHP_EOL . "Directory Iterator seek Test" . PHP_EOL;
$dir_iterator = new DirectoryIterator(dirname(__FILE__));
$dir_iterator->seek(1);
try {
$dir_iterator->seek(500); // arbitrarily high seek position
echo $dir_iterator->key() . PHP_EOL;
echo "Is valid? " . (int) $dir_iterator->valid() . PHP_EOL;
} catch (OutOfBoundsException $e) {
echo $e->getMessage() . PHP_EOL;
echo $dir_iterator->key() . PHP_EOL;
echo "Is valid? " . (int) $dir_iterator->valid() . PHP_EOL;
}
Выход теста 3:
Directory Iterator seek Test
90
Is valid? 0
Итак, как можно разумно ожидать узнать, следует ли использовать valid()
для подтверждения действительной позиции после seek($position)
, а также предвидеть, что seek()
может вызвать исключение вместо обновления позиции, так что valid()
вернет true?