Iterators in the Simplest Sense: Traversing Different Data Structures - Extending the scope of iterators: building a file iterator class (
Page 2 of 4 )
In order to demonstrate how the array iterator you learned in the first article can be used for building a file iterator class, let’s first remind ourselves how the previous classes looked, so it’ll be easier for you to understand the process for constructing the file iterator in question. Here’s the list of classes I defined in the first article:
// base abstract 'Iterator' class
class Iterator{
function Iterator(){
if(get_class($this)=='Iterator'||!is_subclass_of
($this,'Iterator')){
trigger_error('This class is abstract. It cannot be
instantiated!',E_USER_ERROR);
}
}
// abstract 'current()' method
function current(){}
// abstract 'prev()' method
function prev(){}
// abstract 'next()' method
function next(){}
// abstract 'end' method
function end(){}
// abstract 'reset()' method
function reset(){}
// abstract 'seek()' method
function seek(){}
// abstract 'count()' method
function count(){}
}
// 'ArrayIterator' subclass
class ArrayIterator extends Iterator{
var $data=array();
function ArrayIterator($data=array()){
if(!is_array($data)){
trigger_error('Data must be an array',E_USER_ERROR);
}
$this->data=$data;
}
// concrete implementation for 'current()' method
function current(){
if(!$data=current($this->data)){
trigger_error('Error retrieving current
element',E_USER_ERROR);
}
return $data;
}
// concrete implementation for 'prev()' method
function prev(){
if(!$data=prev($this->data)){
trigger_error('Error retrieving previous
element',E_USER_ERROR);
}
return $data;
}
// concrete implementation for 'next()' method
function next(){
if(!$data=next($this->data)){
trigger_error('Error retrieving next
element',E_USER_ERROR);
}
return $data;
}
// concrete implementation for 'end()' method
function end(){
if(!$data=end($this->data)){
trigger_error('Error retrieving last
element',E_USER_ERROR);
}
return $data;
}
// concrete implementation for 'reset()' method
function reset(){
if(!$data=reset($this->data)){
trigger_error('Error retrieving first
element',E_USER_ERROR);
}
return $data;
}
// concrete implementation for 'seek()' method
function seek($pos){
if(!is_int($pos)&&$pos<0){
trigger_error('Invalid offset',E_USER_ERROR);
}
if(!$data=$this->data[$pos]){
trigger_error('Error seeking element',E_USER_ERROR);
}
return $data;
}
// concrete implementation for 'count()' method
function count(){
if(!$data=count($this->data)){
trigger_error('Error counting
elements',E_USER_ERROR);
}
return $data;
}
}
Now that you hopefully recalled the signature for the above classes, it’s time to create the corresponding file iterator class that I mentioned before, this time using the same set of methods exposed by the “ArrayIterator” class. Please study the class defined below:
class FileIterator extends ArrayIterator{
var $data=array();
function FileIterator($file){
if(!file_exists($file)){
trigger_error('Invalid input file',E_USER_ERROR);
}
$this->data=file($file);
}
}
Did you think it was harder to build? No, it wasn’t. As you can see, I created a “FileIterator” class merely by deriving a subclass from the array iterator that I defined previously. In this case, Inheritance plays a very important role. It allowed me to build a class which is capable of traversing a simple text file passed as input parameter, in this case by overriding the corresponding constructor.
As you’ve realized, the remaining methods, such as “prev()”, “next()”, “current()” and so forth, have been inherited from the parent array iterator class, and are used to iterate over the array obtained by the following line:
$this->data=file($file);
Even when I used some basic PHP built-in functions for creating the above “FileIterator” class, its functionality is really remarkable. Just stay away for a moment from thinking of sophisticated applications and focus yourself on simpler ones. If your storage needs are largely covered with flat files, the “FileIterator” class might be used as part of a more complex application, providing a simple but powerful system for navigating back and forth between file lines.
At this point, you saw how easy it is to define a “FileIterator” class, having previously written the respective array iterator. Therefore, setting up an example would be a good idea, because in this way you would see how a sample text file can be traversed by this class. To see how this is done, please read the next section.
| | Discuss Iterators in the Simplest Sense: Traversing Different Data Structures | | | | | | | In this second article, the Iterator pattern is applied to the development of... | | | | | | Thanks. Learned a thing or two again. Nice to see how the base class can be extended... | | | | | | Hi Matthijs,
Thanks again for keeping yourself reading my PHP articles, and of... | | | | | | Hi Matthijs,
The code has been corrected. Again, thanks for spotting... | | | | | | Thank you Charles for correcting the code of the article. I truly appreciate that.... | | | | | | "I'll provide you with a concise explanation of what an Iterator is, in conjunction... | | | | | | Hello Matthijs,
Thank you again for commenting on this article, as well as for... | | | | | | Id love to see you write a indepth series on AJAX. | | | | | | Dear Jonathan,
I'd like to thank you for your compliments on this tutorial, and... | | | | | | Thanks for taking the time to reply Alejandro. Appreciated.
Keep up the great... | | | | | | You're very welcome Matthijs. Thank you for your feedback and kind... | | | | | | >>> Post your comment now! | | | | | |
|
 |