Kapitel 3. Iteratoren

"If the programmer can simulate a construct faster than a compiler can implement the construct itself, then the compiler writer has blown it badly."

--Guy Steele

Einleitung

Das Aufzählen oder Durchlaufen der Elemente einer Menge ist ein wiederkehrendes Problem. Beispiele für solche Mengen sind Arrays, die Zeilen einer Textdatei, die Elemente eines XML-Dokumentes oder die Ergebniszeilen einer Datenbankabfrage.

In PHP 3 erfolgte das Durchlaufen eines numerisch indizierten Arrays mit Hilfe einer for()-Schleife (Beispiel 3.1). Hierbei musste der Programmierer auf die Indexgrenzen achten.

Beispiel 3.1: Iterieren von Arrays in PHP 3

<?php
$a = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
 
for ($i = 0; $i < 10; $i++) {
  print $a[$i] . ' ';
}
?>
1 2 3 4 5 6 7 8 9 10


Assoziative Arrays mussten in PHP 3 mit reset(), while(), list() und each() (Beispiel 3.2) verarbeitet werden.

Beispiel 3.2: Iterieren von assoziativen Arrays in PHP 3

<?php
$a = array('key' => 'value');
 
reset($a);
 
while (list($k, $v) = each($a)) {
  print $k . ': ' . $v;
}
?>
key: value


In PHP 4 wurde mit foreach ein neuer Operator eingeführt, der die Arbeit mit assoziativen und numerisch indizierten Arrays vereinfachte und vereinheitlichte (Beispiel 3.3). Nun war es nicht mehr Aufgabe des Programmierers, sich um Dinge wie Indexgrenzen oder das Fortschreiten zum nächsten Element zu kümmern.

Beispiel 3.3: Iterieren von Arrays in PHP 4

<?php
$a = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
$b = array('key' => 'value');
 
foreach ($a as $v) {
  print $v . ' ';
}
 
foreach ($b as $k => $v) {
  print $k . ': ' . $v;
}
?>
1 2 3 4 5 6 7 8 9 10
key: value


Bereits in PHP 4 war es möglich, den foreach-Operator auf ein Objekt anzuwenden. In diesem Fall wurden die Instanzvariablen des Objektes wie ein assoziatives Array durchlaufen (Beispiel 3.4). Dies ist in PHP 5 weiterhin möglich, jedoch werden hierbei nur die öffentlichen Instanzvariablen berücksichtigt.

Beispiel 3.4: Verwendung von foreach() mit Objekten

<?php
class Test {
  var $a = 1;
  var $b = 2;
}
 
$test = new Test;
 
foreach ($test as $name => $value) {
  print "$name$value\n";
}
?>
a: 1
b: 2


An dieser Stelle wünschen wir uns ein Konzept, das die Vereinheitlichung von assoziativen und numerisch indizierten Arrays verallgemeinert und auf Objekte erweitert. Dieses Konzept finden wir im Entwurfsmuster (siehe Teil II. Entwurfsmuster in PHP anwenden) des Iterators, das wir im Folgenden diskutieren wollen.

Ein Iterator ermöglicht den generischen Zugriff auf die Elemente einer Menge, ohne dass die Struktur der Menge oder die Implementierung der einzelnen Elemente bekannt sein muss. Bei den Elementen einer solchen Menge kann es sich beispielsweise um die Zeilen einer Textdatei, die Elemente eines XML-Dokumentes oder die Ergebniszeilen einer Datenbankabfrage handeln.