Discussion:
IteratorAggregate und RecursiveIterator
(zu alt für eine Antwort)
Stefan+ (Stefan Froehlich)
2022-03-14 10:57:50 UTC
Permalink
Ich habe da eine Collection, die implementiert \Iterator und für
ausgewählte Anwendungsfälle auch (davon abgeleitet)
\RecursiveIterator.

\Iterator ist klassisch implementiert; die Klasse enthält ein Array,
auf das werden current(), next() etc. angewendet. Nun reicht das
leider nicht immer aus, da gelegentlich verschachtelt iteriert wird,
was wg. des Array-Pointers nicht funktioniert.

Nötig wäre wohl die Implementierung von \IteratorAggregate, damit
foreach() den dort erstellten Iterator statt des Array-Pointers
verwendet. Das geht aber nicht, weil \IteratorAggregate ebenso wie
\RecursiveIterator eine Erweiterung von \Iterator darstellt, was wg.
Mehrfachvererbung nicht sein darf.

Ich behelfe mir damit, $object->getIterator() zu verwenden, wenn
iteriert werden soll, aber schön ist das nicht - ich vergesse
gelegentlich darauf, der Unterschied fällt erst auf, wenn
verschachtelt iteriert wird, und selbst dann wird kein Fehler
geworfen, sondern einfach ein falsches Ergebnis produziert.

Komme ich irgendwie drumherum, oder habe ich einfach Pech gehabt?

Servus,
Stefan
--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Wolke Nummer sieben zum verlieben. Mit Stefan. Ein traumhaftes Vergnügen!
(Sloganizer)
Karl Pflästerer
2022-03-15 21:38:25 UTC
Permalink
Post by Stefan+ (Stefan Froehlich)
Ich habe da eine Collection, die implementiert \Iterator und für
ausgewählte Anwendungsfälle auch (davon abgeleitet)
\RecursiveIterator.
\Iterator ist klassisch implementiert; die Klasse enthält ein Array,
auf das werden current(), next() etc. angewendet. Nun reicht das
leider nicht immer aus, da gelegentlich verschachtelt iteriert wird,
was wg. des Array-Pointers nicht funktioniert.
Nötig wäre wohl die Implementierung von \IteratorAggregate, damit
foreach() den dort erstellten Iterator statt des Array-Pointers
verwendet. Das geht aber nicht, weil \IteratorAggregate ebenso wie
\RecursiveIterator eine Erweiterung von \Iterator darstellt, was wg.
Mehrfachvererbung nicht sein darf.
Ich behelfe mir damit, $object->getIterator() zu verwenden, wenn
iteriert werden soll, aber schön ist das nicht - ich vergesse
gelegentlich darauf, der Unterschied fällt erst auf, wenn
verschachtelt iteriert wird, und selbst dann wird kein Fehler
geworfen, sondern einfach ein falsches Ergebnis produziert.
Komme ich irgendwie drumherum, oder habe ich einfach Pech gehabt?
Was meinst du mit verschachtelt iteriert?
Iterierst du (Schleife in Schleife) über dasselbe Objekt mehrfach?
Oder hast du eine tiefere baumstruktur, über die du (depth first oder
breadth first) iterierst?
Stefan+ (Stefan Froehlich)
2022-03-16 09:22:55 UTC
Permalink
Post by Karl Pflästerer
Post by Stefan+ (Stefan Froehlich)
Ich behelfe mir damit, $object->getIterator() zu verwenden, wenn
iteriert werden soll, aber schön ist das nicht - ich vergesse
gelegentlich darauf, der Unterschied fällt erst auf, wenn
verschachtelt iteriert wird, und selbst dann wird kein Fehler
geworfen, sondern einfach ein falsches Ergebnis produziert.
Komme ich irgendwie drumherum, oder habe ich einfach Pech gehabt?
Was meinst du mit verschachtelt iteriert?
Iterierst du (Schleife in Schleife) über dasselbe Objekt mehrfach?
Typischerweise schon, ja.

Nicht explizit, das passiert eher versehentlich, wenn z.B. irgendwo
eine Hilfsmethode das größte Element oder eine Summe der Collection
sucht - und dieses Konstrukt irgendwann im Zug einer
Weiterentwicklung von viel weiter oben iterativ aufgerufen wird.

Klar *kann* man das auflösen (und sollte man nach dem Reinheitsgebot
wohl auch), aber wenn nur genügend Ebenen dazwischen sind, fällt es
halt erst im Fehlerfall auf. In der Regel lasse ich den Code dann
auch so (nur halt mit explizitem getIterator()), weil es bezüglich
Performance (bei Collections mit <10 Elementen) völlig egal ist und
die API schlank hält.
Post by Karl Pflästerer
Oder hast du eine tiefere baumstruktur, über die du (depth first
oder breadth first) iterierst?
Nein, meine Collections implementieren (grundsätzlich, d.h. schon in
der abstrakten Basisklasse) RecursiveIterator, wobei es der
jeweiligen Implementierung obliegt, das mit Leben zu erfüllen.
Erschien mir seinerzeit eine gute Idee, weil es nichts kostet und
ich mir eine gesonderte Klasse RecursiveCollection erspare. Dass
ich mir damit die Implementierung von \Iterator verbaue, ist mir
erst später aufgefallen, als ich das zum ersten Mal gebraucht hätte.

Und irgendwie finde ich das dumm, weil die beiden Interfaces in
keinerlei Konflikt zueinander stünden - dass man sie nicht beide
nebeneinander implementieren kann, liegt einzig und alleine an der
Erbhierarchie.

Servus,
Stefan
--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Stefan - beglücken!? Aber blicken ist verständiger.
(Sloganizer)
Loading...