Можем ли мы использовать IterateAggregate или Iterator в цикле foreach в php?
Я новичок в php и учусь на php.net. В примечании на этой странице ( http://php.net/manual/en/class.traversable.php) говорится, что:
Внутренние (встроенные) классы, которые реализуют этот интерфейс, могут использоваться в конструкции foreach и не требуют реализации IteratorAggregate или Iterator.
О чем говорит эта записка? Означает ли это, что мы можем использовать IteratorAggregate или Iterator внутри цикла foreach без какого-либо класса или, может быть, я ошибаюсь. Может кто-нибудь сказать, что говорит эта записка??
1 ответ
IteratorAggregate
интерфейс для создания внешнего итератора, который позволяет вам перемещаться по объектам пользовательских классов, используя foreach
:
class FooBarClass implements IteratorAggregate
{
public $property = "Nothing to see";
public function __construct()
{
}
public function getIterator()
{
return new ArrayIterator($this);
}
}
$obj = new FooBar;
foreach($obj as $key => $value) {
print(var_dump($key, $value) . "\n");
}
Iterator
также является интерфейсом для внешних итераторов, но позволяет вашим классам или объектам выполнять внутреннюю итерацию:
class myIterator implements Iterator
{
private $position = 0;
private $array = array('one', 'two', 'three');
function rewind()
{
$this->position = 0;
}
function current()
{
return $this->array[$this->position];
}
function key()
{
return $this->position;
}
function next()
{
++$this->position;
}
function valid()
{
return isset($this->array[$this->position]);
}
}
Тем не менее, вы все равно можете пройти ваши объекты так же, как с IteratorAggregate
,
Разница между ними заключается в том, что IteratorAggregate
легче реализовать, чем итератор, и, как правило, быстрее. Недостатком является то, что он предназначен только для обхода и не предоставляет методов next(), key() и т. Д., Так как они не вызываются во время обхода foreach.
В то время как Iterator
(или, более конкретно, OuterIterator или (проще) IteratorIterator) позволяет вам гораздо более точно контролировать итерацию вашего объекта и добавлять пользовательские исключения при сбоях next(), key() или prev (), caching () и т. д.,
Примечание, на которое вы ссылаетесь, означает, что некоторые внутренние классы PHP (написанные на языке C) могут напрямую реализовывать этот интерфейс. Любой пользовательский класс, который должен реализовать Traversable, должен сделать это путем реализации IteratorAggregate или Iterator или другого перехода от Traversable. Смотрите Pro PHP от Кевина Макартура с. 143f.
Сам интерфейс Traversable является абстрактным базовым интерфейсом (без методов, как показано в кратком описании интерфейса), создание которого невозможно. Однако его можно использовать для проверки возможности прохождения класса с помощью foreach или нет.
Traversable {
}
Часть путаницы состоит в том, что объекты и массивы не реализуют "Traversable", но могут быть переданы через foreach, но вы не можете проверить совместимость foreach, используя instanceof
проверьте или введите подсказку.
$myarray = array('one', 'two', 'three');
$myobj = (object)$myarray;
if ( !($myarray instanceof \Traversable) ) {
print "myarray is NOT Traversable";
}
if ( !($myobj instanceof \Traversable) ) {
print "myobj is NOT Traversable";
}
Как упоминалось ранее, каждый объект может быть пройден с помощью foreach, но тогда вы можете просто получить доступ к публичным свойствам. Цитирование из руководства PHP по итерации объекта:
PHP 5 предоставляет способ определения объектов, поэтому можно выполнять итерацию по списку элементов, например, с помощью оператора foreach. По умолчанию все видимые свойства будут использоваться для итерации.
Итак, если вы инкапсулируете объект с закрытыми и защищенными значениями и пишете методы getter и setter для доступа к нему, вам может потребоваться, чтобы ваш класс реализовал IteratorAggregate или Iterator и написал логику, чтобы эти значения были доступны в циклах foreach по мере необходимости.
Короче говоря, объекты, которые реализуют интерфейс Traversable (через Iterator или IteratorAggregate), "действуют как массив". Тем не менее, это не обязательно для итерации объекта. Но вам нужно реализовать Iterator, если вы хотите изменить их поведение. Та же логика применима к встроенным классам.