note 67839 deleted from language.oop5.iterations by bjori

From: Date: Wed, 05 Jul 2006 21:14:34 +0000
Subject: note 67839 deleted from language.oop5.iterations by bjori
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-114430@lists.php.net to get a copy of this message
Note Submitter: baldurien at bbnwn dot eu Reason: 5 ---- Beware of how works iterator in PHP if you come from Java! In Java, iterator works like this : <?php interface Iterator<O> { boolean hasNext(); O next(); void remove(); } ?> But in php, the interface is this (I kept the generics and type because it's easier to understand) <?php interface Iterator<O> { boolean valid(); mixed key(); O current(); void next(); void previous(); void rewind(); } ?> 1. valid() is more or less the equivalent of hasNext() 2. next() is not the equivalent of java next(). It returns nothing, while Java next() method return. PHP's next() method will simply move forward. Here is a sample with an array, first in java, then in php : <?php class ArrayIterator<O> implements Iterator<O> { private final O[] array; private int index = 0; public ArrayIterator(O[] array) { this.array = array; } public boolean hasNext() { return index < array.length; } public O next() { if ( !hasNext()) throw new NoSuchElementException('at end of array'); return array[index++]; } public void remove() { throw new UnsupportedOperationException('remove() not supported in array'); } } ?> And here is the same in php (using the appropriate function) : <?php /** * Since the array is not mutable, it should use an internal * index over the number of elements for the previous/next * validation. */ class ArrayIterator implements Iterator { private $array; public function __construct($array) { if ( !is_array($array)) throw new IllegalArgumentException('argument 0 is not an array'); $this->array = array; } public function valid() { return current($this->array) !== false; // that's the bad method (should use arrays_keys, + index) } public function key() { return key($this->array); } public function current() { return current($this->array); } public function next() { if ( $this->valid()) throw new NoSuchElementException('at end of array'); next($this->array); } public function previous() { // fails if current() = first item of array previous($this->array); } public function rewind() { reset($this->array); } } ?> The difference is notable : don't expect next() to return something like in Java, instead use current(). This also means that you have to fetch your collection to set the current() object. Also, another difference : <?php class ArrayIterable<O> implements Iterable<O> { private final O[] array; public ArrayIterable(O[] array) { this.array = array; } public Iterator<O> iterator() { return new ArrayIterator(array); } } ?> When using an Iterable, in Java 1.5, you may do such loops : <?php for ( String s : new ArrayIterable<String>(new String[] {"a", "b"})) { ... } ?> Which is the same as : <?php Iterator<String> it = new ArrayIterable<String>(new String[] {"a", "b"}); while (it.hasNext()) { String s = it.next(); ... } ?> While in PHP it's not the case : <?php foreach ( $iterator as $current ) { ... } ?> Is the same as : <?php for ( $iterator->rewind(); $iterator->valid(); $iterator->next()) { $current = $iterator->current(); ... } ?> (I think we may also use IteratorAggregate to do it like with Iterable). Take that in mind if you come from Java. I hope this explanation is not too long...

« previous php.notes (#114430) next »