0

我只是从一本书中了解 PHP 中的 OOP,而关于迭代器和迭代的部分让我很困惑。

据我了解,我认为为了遍历对象的属性,您需要实现内置类 Iterator。然后实现 IteratorAggregate 接口并在其中创建一个 getIterator 方法。但是,我目前对这些元素中的每一个所扮演的角色以及它们需要以什么格式编写感到困惑。换句话说,我只是在寻找对这些概念的简单(简单的英语)解释和一个简单的例子。任何帮助将不胜感激!!!!!

并提前感谢您的时间和帮助!!!!

4

2 回答 2

2

你想要循环的东西必须实现Traversable。但是,您不能Traversable直接实施;您必须实现其子类型之一。你将如何做事取决于对象将如何被使用。

如果你愿意,你可以实现Iterator. 如果您的类型已经打算成为仅转发的内容列表,那它就足够了。如果您决定构建一个迭代器,您将有 5 种方法可以实现:

  • current,它检索当前位置的值;
  • key,它检索当前位置的密钥;
  • next,前进到下一个位置;
  • rewind,将当前位置重置为第一个;和
  • validfalse,如果迭代从被迭代的东西列表的末尾脱落,则返回。

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,它会返回可遍历的内容。如果您的某些东西已经可以被内置 SPL 迭代器之一遍历,或者可以轻松地简化为数组或其他东西,那么这是一个更好的解决方案。

上面的相同循环,如果在 IteratorAggregate 上调用,将等同于类似

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

getIterator()必须返回一个实现Iterator或一些原始的可遍历的东西,比如一个数组。

对于 Java 风格的迭代器,您可以构建一个 Iterator 子类型,它可以记住它的位置并遍历您的集合,然后IteratorAggregate在您的集合上实现以返回迭代器类型的实例。

于 2013-03-15T20:17:25.890 回答
0

对于基本功能,您只需要为、、、和方法implement Iterator添加相关功能。请参阅下面的示例:rewindvalidkeycurrentnext

  /**
   * 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;

}
于 2013-03-15T20:13:04.913 回答