As you may have guessed, turning the previous “DataIterator” class into an abstract class is only a matter of preceding its name with the keyword “abstract.” So, the simplest way to prevent this base class from being instantiated is by redefining it in the following way:
abstract class DataIterator implements Iterator, Countable { protected $_pointer = 0; protected $_data = array();
public function __construct(array $data) { if (empty($data)) { throw new Exception('Input data must be a non-empty array.'); } $this->_data = $data; }
// implement 'count()' method required by Countable interface public function count() { return count($this->_data); }
// implement 'rewind()' method required by Iterator interface public function rewind() { $this->_pointer = 0; }
// implement 'current()' method required by Iterator interface public function current() { if (!$this->valid()) { return FALSE; } return $this->_data[$this->_pointer]; }
// implement 'valid()' method required by Iterator interface public function valid() { return $this->_pointer < $this->count(); }
// implement 'next()' method required by Iterator interface public function next() { ++$this->_pointer; }
// implement 'key()' method required by Iterator interface public function key() { return $this->_pointer; } } At this point, since the array iterator class has been declared abstract, there’s no point in defining its constructor protected, at least in the context of this particular example. However, if I still want to create a class capable of traversing text files, its definition would remain exactly the same. The following code sample demonstrates this in a nutshell: class FileIterator extends DataIterator { private $_file = 'data.txt';
// override parent constructor public function __construct($file = '') { if ($file !== '') { if (!file_exists($file)) { throw new Exception('Target file must be an existing file.'); } $this->_file = $file; } $data = file($this->_file); parent::__construct($data); } }
As you can see, the source code of the above “FileIterator” class remains unchanged, since that the class accesses the parent’s constructor with no restrictions, without worrying too much if the base array iterator is declared abstract or not. Indeed, this subtle modification regarding the way that the base “DataIterator” class has been defined allows you to easily get rid of a protected constructor. However, there are certain situations where a restrictive constructor might be used for purposes other than preventing the instantiation of its originating class. But I’m getting ahead of myself, since that topic will be covered in depth in a subsequent article of this series. So, returning to the previous file iterator, it’s time to give it a try and find out if it works the same, now that its parent has been turned into an abstract class. To get the answer to this mystery, you’ll have to go ahead and read the following section.
blog comments powered by Disqus |
|
|
|
|
|
|
|