PHP und Java haben aus meiner Sicht vieles gemeinsam, sei es nun die ähnliche Syntax oder der zu unrecht schlechte Ruf beider Sprachen. Spätestens jedoch wenn es um die Sortierung von beliebigen Objekten geht zeigt sich deutlich, dass Java die Nase vorn hat.
Ein Grund mehr mal über den PHP-Tellerrand zu spicken und einen kleine Ausflug in die Java-Welt zu machen.
PHP bietet zwar mit diversen Array-Funktionen schon einige Möglichkeiten der Sortierung an, diese sind aber doch recht starr und man stößt schnell an gewisse Grenzen, wenn man mehr als nur einfache Datentypen sortieren will, da sowohl die Sortierlogik, wie auch der Vergleich der Objekte sind nach außen in einer Funktion zusammengefasst sind.
Wie funktioniert das denn nun in der Java-Welt? In Java müssen Objekte durch das Interface “Comparable” als sortierbar gekennzeichnet werden. Die meisten Standardklassen implementieren das bereits.
Das Interface schreibt die Methode ‘compareTo” vor, die es dem Objekt erlaubt, sich mit anderen Objekten zu vergleichen. Der Rückgabewert kann 1, 0 oder -1 sein.
Dazu ein kleines Beispiel:
Leider gibt ist in der SPL noch kein derartiges Interface vorhanden, also schreibe ich es einfach mal selbst.
<?php interface Custom_Compareable { public function compareTo($object); }
Dann brauchen wir noch ein Objekt zum Vergleichen.
<?php class Person implements Custom_Comparable { private $_id; private $_vorname; private $_nachname; private $_geburtsdatum; public function __construct($id) { $this->_id = $id; } // Getter und Setter... public function compareTo($object) { if (!$object instanceof Person) { throw new InvalidArgumentException(); } if ($this->_id < $object->_id) { return -1; } else if ($this->_id == $object->_id) { return 0; } else { return 1; } } }
Damit können nun Objekte vom Typ Person standardmäßig nach ihrer Id unabhängig vom Suchalgorithmus sortiert werden.
<?php $p1 = new Person(3); $p2 = new Person(2); if ($p1->compareTo($p2) < 0) { // swap($p1, $p2) }
Bis jetzt haben wir zwar schon die Sortierlogik vom Vergleich der Objekte lösen können, aber trotzdem noch nicht viel gewonnen, da nur die Ids verglichen werden. Für abweichende Sortierungen lässt sich der Vergleich nun auch noch vom Personen-Objekt lösen. Dafür bietet Java das Interface “Comparator” an, bei uns wird es nun das Custom_Comparator-Interface.
<?php interface Custom_Comparator { public function compare($object1, $object2); }
Die Methode “compare()” hat die gleichen Rückgabewerte wie “compareTo()” und kann dadurch genauso verwendet werden.
<?php class PersonComparatorVorname implements Custom_Comparator { public function compare($object1, $object2) { if (!$object1 instanceof Person || !$object2 instanceof Person) { throw new InvalidArgumentException(); } if ($object1->getVorname() < $object2->getVorname()) { return -1; } else if ($object1->getVorname() == $object2->getVorname()) { return 0; } else { return 1; } } }
Durch diese beiden Interfaces haben wir nun die Möglichkeit, unsere Objekte beliebig sortieren zu lassen. Über die Wertigkeit der Objekte entscheidet nun das Objekt selbst, bzw. ein passender Comparartor. Wie die Objekte letztendlich sortiert werden ist egal, da die Logik an einer anderen Stelle implementiert wird und nun für alle Objekte gleich funktioniert, wenn diese “Comparable” sind.
<?php $listeMitPersonen = array(new Person(1), new Person(2)); $comparator = new PersonComparatorVorname(); // die Funktionen stehen als Pseudocode bubblesort($listeMitPersonen); bubblesort($listeMitPersonen, $comparator); quicksort($listeMitPersonen); quicksort($listeMitPersonen, $comparator);
Und auch die Logik für auf- oder absteigende Reihenfolge lässt sich komplett getrennt dank Dekorator-Pattern auslagern.
<?php class ReverseComparator implements Custom_Comparator { private $_comparator; public function __construct(Custom_Comparator $comparator) { $this->_comparator = $comparator; } public function compare($object1, $object2) { return $this->_comparator->compare($object1, $object2) * (-1); } }
06.09.2010 um 13:00 Uhr
Das Comparator-Interface fehlt mir in PHP auch, helfe mir meistens mit den usort-Funktionen und create_function() aus, was natürlich kein bisschen objektorientiert ist.
In Kombination sollte das aber auch sehr schön funktionieren:
[code]
usort($listeMitPersonen, array($comparator, 'compare'));
[/code]
Pingback: Java interfaces in PHP | patrickburke.de
06.09.2010 um 17:57 Uhr
Wahrscheinlich eine Thematik mit der sich jeder schon mal rumschlagen musste
Kurze Frage: Inwiefern erlaubt der instanceof Operator Polymorphismus? Ich weis das z.B. is_a das ziemlich gut handlet aber wie stehts mit instanceof?
Gruss
06.09.2010 um 19:42 Uhr
Die Funktion is_a() wurde mit PHP Version 5 durch den Operator instanceof ersetzt und ich konnte in den letzten Jahren keine gravierenden Unterschiede feststellen.
06.09.2010 um 21:18 Uhr
@Daniel: Hossa… frage mich wieso mein code keine Fehler geworfen hat… in 5.3 ist is_a übrigens nicht mehr deprecated.
06.09.2010 um 21:21 Uhr
Stimmt, das habe ich inzwischen auch gelesen. Werde den instanceof-Operator dennoch beibehalten, dann muss ich nicht wieder umdenken, wenn ich mal was in Java schreibe.
Pingback: Tweets that mention Besser Sortieren mit PHP dank Java Interfaces « ebene7 -- Topsy.com
11.09.2010 um 14:00 Uhr
Feine Sache, ich bin auch in beiden Welten (Java und PHP) zu Hause. Schöner Artikel
11.09.2010 um 14:02 Uhr
Vielen Dank
Pingback: Sortieren mit PHP5 Closures und dem Java Comparator Pattern – ebene7