5

私は SPL イテレータについて頭を悩ませようとしていますが、それを処理する 2 つの方法を考え出しました。最初のバージョンはそれほど複雑ではないように見えますが、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()IteratorgetChocolated()IteratorAggregateforeach

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

状況によります。チョコレートの箱には複数のコレクションが含まれていますか? その場合、コレクションをメンバーにする必要があります。

このように考えてください。チョコレートの箱はコレクション (PersonList など) か、コレクションを所有するもの (つまり、車は最後の所有者のコレクションを所有する場合があります) です。

これは最初のグループに該当すると思います

:)

于 2008-10-19T06:15:59.340 に答える
1

あなたのチョコレートの比喩が実際のクラスにかなり正確であると仮定すると、最初のグループもお勧めします。

チョコレートの箱は実際にはチョコレートのコレクションです。そのため、その箱内のチョコレートを反復処理することは理にかなっています。別のチョコレートリストを追加しても、実際には何の価値もありません。不要なレイヤーを追加しているように見えます.

于 2008-10-19T06:23:55.580 に答える
0

簡単に言えば、コンテナはイテレータを実装する場所です。

于 2008-10-19T11:58:29.507 に答える
0

まあ、私はPHPを知らないので、質問に適切に答えることができませんが、私が知っている分野に関連付けてみます.

C# には、IEnumerable と IEnumerator の 2 つのインターフェイスがあります。あなたの例では、BoxOfChocolates は Enumerable になり、Chocolates は Enumerator になります。

Enumerable には、Enumerator を返すメソッドしかありません。列挙子には、現在のアイテムの概念と、次のアイテムに移動する手段があります。ほとんどの場合、Enumerator クラスは「見えません」。たとえば、「foreach(boxOfChoclates のチョコレート項目)」行では、boxOfChocolates は Enumerable です。Enumerator オブジェクトは foreach によって完全に隠されています。

于 2008-10-19T11:32:28.890 に答える
0

コレクションとイテレータを分けておくべきだと思います。コレクションにはイテレータが含まれることが多いという@James Curranに同意します。実際、コレクションには複数のイテレータを含めることができます。たとえば、キャンディーとナッツをスキップするイテレータが必要な場合があります (ただし、通常は順序を逆にするイテレータが必要です)。この場合、next() メソッドの意味が変わります。これを処理するには、独自の反復セマンティクスを含む別のクラスに反復子を実装します。適切な並べ替えの反復子を取得するためのメソッドをコレクションに提供します。それは本当に関心の分離の問題です。コレクションは、ユーザーがそれをどのように反復するかを気にしません。それは反復子の関心事です。

于 2008-10-19T12:11:50.637 に答える