2008-10-19 5 views
5

Ich versuche, SPL-Iteratoren in den Griff zu bekommen, und ich habe zwei Möglichkeiten gefunden, damit umzugehen. Ich sehe die erste Version weniger kompliziert, aber die zweite Version hat ein Gefühl der Komposition (denke ich).Sollte ein Objekt einen Iterator implementieren oder ein anderes Objekt enthalten, das einen Iterator implementiert

Was sehe ich nicht ist, welches dem anderen vorzuziehen ist? Oder mache ich das nur etwas komplizierter?

Hier sind meine Gedanken:

Das Objekt implementiert einen Iterator:

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 


} 

Das Objekt enthält ein Iterierte-able Objekt:

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 

} 

Antwort

2

Es hängt von der Situation. Enthält die Pralinenschachtel mehrere Kollektionen? Wenn dies der Fall ist, müssen die Sammlungen Mitglieder sein.

Denken Sie auf diese Weise. Ist eine Schachtel Pralinen eine Sammlung (d. H. PersonList) oder etwas, das eine Sammlung besitzt (d. H. Ein Auto kann eine Sammlung seiner letzten Besitzer besitzen).

Ich denke, dies fällt unter der ersten Gruppe

:)

1

i auch die erste Gruppe würde vorschlagen, Ihre Schokolade Metapher unter der Annahme ist ziemlich genau die tatsächliche Klasse.

eine Schachtel Pralinen ist wirklich Ihre Sammlung von Pralinen, und als solche macht es Sinn, über die Pralinen in dieser Box iterieren zu wollen. Das Hinzufügen einer separaten Schokoladenliste fügt keinen wirklichen Mehrwert hinzu und scheint nur eine unnötige Schicht hinzuzufügen.

0

Nun, ich kenne PHP nicht, daher kann ich die Frage nicht richtig beantworten, aber ich werde versuchen, es mit einem Bereich in Verbindung zu bringen, den ich kenne.

In C# gibt es zwei Schnittstellen: IEnumerable und IEnumerator. In Ihrem Beispiel wären BoxOfChocolates Enumerable, Chocolates wäre ein Enumerator.

Enumerables haben nur eine Methode, die einen Enumerator zurückgibt. Aufzählungselemente haben ein Konzept eines aktuellen Elements und ein Mittel, um zum nächsten Element zu gelangen. In den meisten Fällen wird die Enumerator-Klasse nicht "gesehen". Beispielsweise ist in der Zeile "foreach (Schokoladenartikel in boxOfChocolates)" boxOfChocolates ein Enumerable; Das Enumerator-Objekt wird vollständig von der Foreach verborgen.

0

Ganz einfach der Container ist der Ort, um den Iterator zu implementieren.

0

Ich denke, Sie sollten Ihre Sammlungen getrennt von Ihren Iteratoren halten. Ich würde @James Curran zustimmen, dass Sammlungen oft Iteratoren haben - tatsächlich könnten sie mehrere haben. Zum Beispiel möchten Sie vielleicht einen Iterator, der Bonbons mit Nüssen überspringt (obwohl der typische Fall ist, einen zu wünschen, der die Reihenfolge umkehrt). In diesem Fall ändert sich die Bedeutung der next() -Methode. Um dies zu handhaben, implementieren Sie Iteratoren in separaten Klassen, die ihre eigene Iterationssemantik enthalten. Stellen Sie Methoden in der Auflistung bereit, um Iteratoren der richtigen Sortierung zu erhalten. Es ist wirklich eine Frage der Trennung von Anliegen. Der Sammlung ist es egal, wie der Benutzer darüber iteriert, das ist der Iterator.

4

bbxbby, die beste Lösung ist normalerweise die einfachste. Sie verschmelzen definitiv nicht Dinge, die separate Iterator-Objekte erstellen.In der Tat unterstützt und fördert PHP eine solche Aggregation mit IteratorAggregate Schnittstelle. Objekte, die IteratorAggregate implementieren, müssen die getIterator() Methode enthalten, die Iterator zurückgibt. Es ist wirklich, was Ihre Methode getChocolated() tut. Das Schöne an IteratorAggregate ist, dass Sie ein Objekt davon direkt an foreach Schleife übergeben können. Ihr Code könnte so aussehen wie diese, wenn es mit:

class BoxOfChocolates implements IteratorAggregate 

    private $chocolates = array(); 

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

} 

Und dann irgendwo im Code:

$box = new BoxOfChocolates(); 
foreach ($box as $chocolate) { ... }