Artikelformat

Das Iterator-Interface

Diese Woche gibt es leider nur einen kurzen Artikel, da ich keinen vernünftigen Zugang ins Internet habe und somit meine Recherche-Möglichkeiten begrenzt sind. Darum betrachte ich heute kurz das Iterator-Interface. Da dieses Interface auch für PHP 5.3 wichtig ist, sollte dieses Interface dem interessierten Entwickler bekannt sein.

Das Interface stellt eine Möglichkeit bereit über eine Menge von Objekten zu iterieren. Ein Beispiel für eine Implementierung ist das array. In verschiedenen Projekten habe ich die Variante gesehen, dass die Objekte intern in einem Array verwaltet wurden. Sobald man über diese Objekte iterieren wollte, wurde das Array nach außen gegeben, damit man das foreach-Konstrukt nutzen konnte. Heutzutage sollte man lieber die Kapselung geschlossen lassen und das Iterator-Interface implementieren.

Als Beispiel entwickeln wir ein Objekt, dass mit einem String instanziiert wird und über das man anschließend mit foreach laufen kann. Es werden „Wörter“ als einzelne Rückgabewerte betrachtet. Also wird der Eingabe-String an einem Whitespace bzw. Komma-Zeichen gesplittet. Die „WordObject“-Klasse muss nun das mehrfach angesprochene Iterator-Interface implementieren. Hierzu sind die Methoden rewind, current, key, next und valid zu implementieren.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class WordObject implements Iterator {
 
    private $innerArray;
    private $pointer = 0;
 
    public function __construct($inputstring) {
        $this->innerArray = preg_split("/[\s,]+/",  trim($inputstring));
    }
 
    public function current() {
        return $this->innerArray[$this->pointer];
    }
 
    public function key() {
        return $this->pointer;
    }
 
    public function next() {
        ++$this->pointer;
    }
 
    public function rewind() {
        $this->pointer=0;
    }
 
    public function valid() {
        return isset($this->innerArray[$this->pointer]);
    }
}

Man kann das Objekt nun bspw. so nutzen:

1
2
3
4
5
$example = new WordObject("Hello World, this is a Iterator test");
 
foreach ($example as $key => $value) {
    echo $key . ": " . $value . "\n";
}

Dieser Code gibt dann – wie erwartet – folgende Ausgabe aus:

1
2
3
4
5
6
7
0: Hello
1: World
2: this
3: is
4: a
5: Iterator
6: test

Update und Anmerkung:
Wie in den Kommentaren angemerkt, kann man den obigen Code auch einfacher darstellen. Dafür muss das IteratorAggregate-Interface implementiert werden. Den Vorteil kann man vor allem deshalb nutzen, weil intern ein Array genutzt wird. Der Code für die vereinfachte Variante sieht so aus:

1
2
3
4
5
6
7
8
9
10
11
12
class WordObject implements IteratorAggregate {
 
    private $innerArray;
 
    public function __construct($inputstring) {
        $this->innerArray = preg_split("/[\s,]+/",  trim($inputstring));
    }
 
    public function getIterator() {
        return new ArrayObject($this->innerArray);
    }
}