2013-03-15 2 views
0

Я только что узнал о ООП в PHP из книги, а в разделе «Итераторы» и «Итерация» меня насторожило.Общая справка об Итераторах с ООП в PHP

Для того, что я понимаю, я думаю, для того, чтобы пересечь атрибуты объекта, вам нужно реализовать встроенный класс Iterator. Затем выполните интерфейс IteratorAggregate и создайте метод getIterator внутри. Тем не менее, я в настоящее время запутался в роли, которую играют каждый из этих элементов, и в каком формате они должны быть написаны. Другими словами, я просто ищу простое (простое английское) объяснение этих понятий и простой пример. Любая помощь будет принята с благодарностью !!!!!

И спасибо за ваше время и помощь заранее !!!!

ответ

0

Для базовой функциональности вы только действительно нужно implement Iterator и добавить соответствующую функциональность для rewind, valid, key, current и next методов. Ниже для примера:

/** 
    * Awesome 
    * 
    * Do awesome stuff 
    */ 
    final class Awesome implements Iterator 
    { 

    /** 
    * An array of data 
    * 
    * @access private 
    * @var array $_data 
    */ 
    private $_data; 

    /** 
    * Store the initial data 
    * 
    * @access public 
    * @param array $data 
    */ 
    public function __construct(array $data = array()) 
    { 
     $this->_data = $data; 
    } 

    /** 
    * Rewind the iterator 
    * 
    * @access public 
    */ 
    public function rewind() 
    { 
     reset($this->_data); 
    } 

    /** 
    * Validate the existence of the next element 
    * 
    * @access public 
    * @return boolean 
    */ 
    public function valid() 
    { 
     return isset($this->_data[$this->key()]); 
    } 

    /** 
    * Return the current key 
    * 
    * @access public 
    * @return integer 
    */ 
    public function key() 
    { 
     return key($this->_data); 
    } 

    /** 
    * Return the current value 
    * 
    * @access public 
    * @return mixed 
    */ 
    public function current() 
    { 
     return current($this->_data); 
    } 

    /** 
    * Increment the iteration index 
    * 
    * @access public 
    */ 
    public function next() 
    { 
     next($this->_data); 
    } 

    } 

    // Instantiate a new Awesome object 
    $awesome = new Awesome(array('Michael', ' ', 'Rushton', ' ', 'is', ' ', 'awesome', '!')); 

    // Iterate over the awesome object and output a universal truth 
    foreach ($awesome as $almost_awesome) 
    { 
    echo $almost_awesome; 
    } 

Если вы хотите, чтобы вместо того, чтобы перебирать свойства объекта просто изменить __construct к:

/** 
* Construct the object 
* 
* @access public 
*/ 
public function __construct() 
{ 

    // Get the properties 
    $object_vars = get_object_vars($this); 

    // Unset the data reference 
    unset($object_vars['_data']); 

    // Set the data 
    $this->_data = $object_vars; 

} 
+0

Спасибо Майкл за этот хорошо отмеченный пример !!!! Я согласен с выходом! : P Cheers – user1216849

2

вещь, которую вы хотите перебираем должны реализовать Traversable. Однако вы не можете реализовать Traversable напрямую; вам нужно реализовать один из его подтипов. Как вы будете делать все зависит от того, как будет использоваться объект.

Если вы хотите, вы можете просто реализовать Iterator. Это работает достаточно хорошо, если ваш тип предназначен только для пересылки только вперед. Если вы решили построить итератор, вы будете иметь 5 методов для реализации:

  • current, который извлекает значение в текущем местоположении;
  • key, который извлекает ключ текущего местоположения;
  • next, который переходит в следующее место;
  • rewind, который сбрасывает текущее местоположение до первого; и
  • valid, который возвращает false, если итерация упала с конца перечня переименованного материала.

PHP называет эти методы в ходе итерации. В частности, предположим, что у вас есть такой код:

foreach ($it as $key => $value) { 
    doStuffWith($key, $value); 
} 

Это довольно эквивалентно следующему:

for ($it->rewind(); $it->valid(); $it->next()) { 
    $value = $it->current(); 
    $key = $it->key(); // only if the foreach has a `$key =>` 

    doStuffWith($key, $value); 
} 

В основном вам просто нужно построить тип, который implements Iterator и правильно реагирует на тех методах, вызываемых примерно в таком порядке. В идеале также должно быть возможно, что что-то произойдет между ними ... но это обычно не проблема, если вы не пропустите ссылки вокруг.

Если вам не нужна индивидуальная итерация, вместо этого вы можете просто реализовать IteratorAggregate и вернуть существующий тип итератора, если он способен делать то, что вам нужно.(Например, если вы хотите разрешить цикл по внутреннему массиву, то для работы уже есть ArrayIterator. Не нужно сворачивать самостоятельно.) Для IteratorAggregate вам нужно только реализовать getIterator, который возвращает что-то, что можно пропустить. Это лучшее решение, если у вас есть что-то, что уже может пройти один из built-in SPL iterators, или его можно легко свести к массиву или к чему-то еще.

то же цикл выше, при вызове на IteratorAggregate, будет приравнять к чему-то вроде

foreach ($it->getIterator() as $key => $value) { 
    doStuffWith($key, $value); 
} 

getIterator() должен возвращать либо реализацию Iterator или некоторую примитивную проходимую штучку, как массив.

Что касается итераторов в стиле Java, вы можете создать подтип Iterator, который может запомнить его место и петлю над вашей коллекцией, а затем реализовать в вашей коллекции IteratorAggregate, чтобы вернуть экземпляр типа итератора.

+0

Спасибо, chao. Очень полезно. Особенно это касается использования Traversable. В моем учебнике указано, что реализация Transversable создает фатальную ошибку и просто не делает этого. Однако теперь ясно, что вы просто не можете реализовать прямо! Благодаря!!! – user1216849

+0

@ user1216849: Да ... они, вероятно, полагали, что должен быть способ набрать «намек», «материал, который вы можете« переубедить »или что-то еще, поэтому должен быть общий тип. Но этого недостаточно, чтобы просто сказать: «Вы можете« вывести меня ». Вы должны предоставить способ сделать это, и Traversable не делает этого; это оставляет его подтипы. – cHao

Смежные вопросы