5

我试图了解 SPL 迭代器,我想出了 2 种方法来处理它。我认为第一个版本不那么复杂,但第二个版本有作曲的感觉(我认为)。

我没有看到哪一个比另一个更可取?还是我只是让这件事复杂化了?

以下是我的想法:

该对象实现了一个迭代器:

class BoxOfChocolates implements Iterator {

  private $id
  private $name; // e.g. Valentine's Heart Box
  private $maker; // e.g. Hersheys
  private $items; // array

  public function getChocolates() {
    $query = ...
    foreach($rows as $row) {
      $this->_items[] = new Chocolate() ...
    }
  }

  // ... necessary iterator implementation stuff


}

该对象包含一个可迭代的对象:

class BoxOfChocolates {

  private $id;
  private $name;
  private $maker;
  private $items; // chocolates object

  public function getChocolates() {
    $this->items = new Chocolates();
    $this->items->getChocolates();
  }

}


class Chocolates implements Iterator {

  private $items;

  public function getChocolates() {
    $query = ...
    foreach($rows as $row) {
      $this->_items[] = new Chocolate() ...
    }
  }

  // ... necessary iterator implementation stuff

}
4

6 回答 6

4

bbxbby,最好的解决方案通常是最简单的。您绝对不会使创建单独的迭代器对象的事情变得过于复杂。事实上,PHP 支持并鼓励这种聚合提供IteratorAggregate接口。实现的对象IteratorAggregate必须包含getIterator()方法返回Iterator。这确实是您的getChocolated()方法所做的。好处IteratorAggregate是您可以将它的对象直接传递给foreach循环。使用它时,您的代码可能看起来像这样:

class BoxOfChocolates implements IteratorAggregate

    private $chocolates = array();

    public function getIterator() {
        return new ArrayIterator(new ArrayObject($this->chocolates)));
    }

}

然后,在代码的某处:

$box = new BoxOfChocolates();
foreach ($box as $chocolate) { ... }
于 2008-10-19T22:43:43.577 回答
2

这取决于实际情况。t0 巧克力盒是否包含多个系列?如果是这样,您需要让集合成为成员。

这样想吧。一盒巧克力是一个集合(即PersonList)还是拥有一个集合的东西(即汽车可能拥有它的最后一个所有者的集合)。

我认为这属于第一组

:)

于 2008-10-19T06:15:59.340 回答
1

我也建议第一组,假设您的巧克力隐喻对实际课程非常准确。

一盒巧克力确实是您收集的巧克力,因此想要迭代该盒子中的巧克力是有意义的。添加一个单独的巧克力列表并没有真正增加任何价值,而且似乎只是增加了一个不必要的层。

于 2008-10-19T06:23:55.580 回答
0

好吧,我不懂 PHP,所以我不能正确回答这个问题,但我会尝试将它与我知道的领域联系起来。

在 C# 中,有两个接口:IEnumerable 和 IEnumerator。在您的示例中,BoxOfChocolates 将是 Enumerable,Chocolates 将是 Enumerator。

Enumerables 只有一个返回 Enumerator 的方法。枚举器有一个当前项目的概念,以及移动到下一个项目的方法。在大多数情况下,Enumerator 类不是“可见”的。例如,在“foreach(Chocolate item in boxOfChoclates)”这一行中,boxOfChocolates 是一个 Enumerable;Enumerator 对象被 foreach 完全隐藏。

于 2008-10-19T11:32:28.890 回答
0

很简单,容器就是实现迭代器的地方。

于 2008-10-19T11:58:29.507 回答
0

我认为您应该将集合与迭代器分开。我同意@James Curran 的观点,即集合通常有迭代器——事实上,它们可以有几个。例如,您可能想要一个跳过带有坚果的糖果的迭代器(尽管典型的情况是想要一个颠倒顺序的迭代器)。在这种情况下, next() 方法的含义会发生变化。为了解决这个问题,在包含它们自己的迭代语义的单独类中实现迭代器。在集合中提供方法以获得正确排序的迭代器。这实际上是一个关注点分离的问题。集合不关心用户如何迭代它,这是迭代器的关注点。

于 2008-10-19T12:11:50.637 回答