2008-10-19 23 views
5

Estoy tratando de entender los iteradores SPL y he encontrado dos formas de manejarlo. Veo que la primera versión es menos complicada, pero la segunda versión tiene una sensación de composición (creo).En caso de que un objeto implemente un iterador u otro objeto que implemente un iterador

¿Qué es lo que no veo es cuál es preferible sobre el otro? ¿O acabo de complicar esto?

Aquí están mis pensamientos:

El objeto implementa un iterador:

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 


} 

el objeto contiene un objeto iterate-poder:

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 

} 

Respuesta

2

Depende de la situación. ¿La caja de chocolates va a contener múltiples colecciones? Si es así, necesita que las colecciones sean miembros.

Piénsalo de esta manera. Es una caja de chocolates una colección (es decir, PersonList) o algo que posee una colección (es decir, un automóvil puede poseer una colección de sus últimos propietarios).

creo que esto cae bajo el primer grupo

:)

1

me gustaría sugerir el primer grupo también, suponiendo que su metáfora chocolate es bastante exacto de la clase real.

una caja de chocolates es realmente su colección de chocolates, y como tal, tiene sentido querer repetir los chocolates dentro de esa caja. agregar una lista de chocolate por separado realmente no agrega ningún valor, y simplemente parece agregar una capa innecesaria.

0

Bueno, no conozco PHP, por lo que no puedo responder correctamente la pregunta, pero intentaré relacionarla con un área que sí conozco.

En C#, hay dos interfaces: IEnumerable e IEnumerator. En su ejemplo, BoxOfChocolates sería Enumerable, Chocolates sería un Enumerator.

Los enumerables simplemente tienen un método que devuelve un enumerador. Los enumeradores tienen un concepto de un elemento actual y un medio para pasar al siguiente elemento. En la mayoría de los casos, la clase Enumerator no se "ve". Por ejemplo, en la línea "foreach (artículo de chocolate en boxOfChoclates)" boxOfChocolates es un enumerable; el objeto Enumerator está completamente oculto por el foreach.

0

Simplemente el contenedor es el lugar para implementar el iterador.

0

Creo que debería mantener sus colecciones separadas de sus iteradores. Estoy de acuerdo con @James Curran en que las colecciones a menudo tienen iteradores, de hecho, podrían tener varias. Por ejemplo, puede querer un iterador que omita dulces con nueces (aunque el caso típico es querer uno que invierta el orden). En este caso, el significado del método next() cambia. Para manejar eso, implemente iteradores en clases separadas que contengan su propia semántica de iteración. Proporcione métodos en la colección para obtener iteradores del tipo apropiado. Es realmente un problema de separación de preocupaciones. A la colección no le importa cómo el usuario itera sobre ella, esa es la preocupación del iterador.

4

bbxbby, la mejor solución suele ser la más simple. Definitivamente no estás complicando demasiado las cosas creando un objeto iterador por separado.De hecho, PHP apoya y fomenta dicha agregación proporcionando la interfaz IteratorAggregate. Los objetos que implementen IteratorAggregate deben contener el método getIterator() que devuelve Iterator. Es realmente lo que hace su método getChocolated(). Lo bueno de IteratorAggregate es que puedes pasar un objeto directamente al foreach loop. Su código puede parecer como éste cuando se utiliza:

class BoxOfChocolates implements IteratorAggregate 

    private $chocolates = array(); 

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

} 

Y luego, en alguna parte del código:

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