Traits in PHP 5.4.0 - Part 3: Traits als Type Hints?

09.03.2012

In Part 1 von Traits in PHP 5.4.0 wurde ein Trait zum Vergleichen von Objekten vorgestellt. Darauf aufbauend folgendes Problem: Wir haben eine Klasse Collection (nur fiktiv, ohne Implementierung), die eine Methode sort(Comparator $comparator) aufweist, mit der die Elemente anhand eines gegebenen Vergleichsfunktionsobjektes sortiert werden. Für mehr Typsicherheit wäre es sicherlich sinnvoll, dass der Comparator auch tatsächlich nur vergleichbare Objekte annimmt, z.B. so:

class Comparator{
	public function compare(Comparable $left, Comparable $right){/* ... */}}

Das funktioniert so nicht. Instanzen der in Part 1 vorgestellten Klasse IntValue könnten nicht damit verglichen werden. Stattdessen wird eine Fehlermeldung ausgeworfen, dass eine Instanz eines Comparable erwartet wird. Man könnte also sagen, dass IntValue zwar Comparable benutzt (daher auch das passende Schlüsselwort use), aber kein Comparable ist. Es handelt sich also um ein Implementierungsdetail.

Der korrekte Weg kann daher nur über ein Interface führen. Möglich wäre beispielsweise, statt des Comparable-Traits nur ein Comparable-Interface zu erstellen und den Trait AbstractComparable, PartialComparable, ComparableTrait, ComparableAspect (oder was immer als Name passend erscheint) zu nennen. Den Trait zu nennen wie die Schnittstelle ist übrigens nicht möglich, Interfaces, Klassen und Traits teilen sich in dieser Hinsicht den Namensraum.

Ein Beispiel für eine solche Konstruktion habe ich bereits vorgestellt – es handelt sich um die Umsetzung des Observer-Patterns in Part 2. IntValue implementiert dort SplSubject, wobei die Implementierung über den Trait SimpleSplSubject erfolgt.

TLDR: Traits sind Implementierungsdetails. Ob und wie sie von einer Klasse benutzt werden, hat Code, der die Klasse einsetzt, nicht zu interessieren.