Im nächsten PHP Release gibt es ein neues Feature für horizontalen Code Reuse: sog. Traits (engl. Merkmal, Charakterzug). Was das ist und wie es funktioniert, erfahrt ihr im folgenden Artikel.
Vererbung: Vertikaler Code Reuse
class A {
public function foo() { ....}
}
class B extends A { }
Bei der objektorientierten Vererbung werden alle nicht-privaten Methoden und Attribute einer Klasse auf die Kind-Klasse vererbt. Das ist toll, denn so braucht man viele Methoden nur einmal zu implementieren, kann sie aber in vielen verschiedenen Klassen wiederverwenden. Das ist vertikaler Code Reuse. Tolle Sache, kein Thema.
Traits: Horizontaler Code Reuse
Abhilfe schaffen hier in PHP 5.4 die sogenannten Traits, welche bereits in Perl 6 oder Scala zur Verfügung stehen. Sie erlauben es dem Entwickler Behaviors (also Verhalten) in Code zu gießen. Diese Traits funktionieren im Prinzip wie Klassen können jedoch – ähnlich wie Interfaces und abstrakte Klassen – nicht instanziiert werden.
Sie sind dazu gedacht, Funktionalitäten zu gruppieren. Einer der Vorteile ist, dass eine Klasse mehrere Traits verwenden kann. Traits beheben somit einige Probleme von single inheritance Sprachen wie PHP oder Java.
Um das eben angesprochene Singleton-Pattern-Problem zu lösen genügt nun ab PHP 5.4 folgene Klassen-Definition:
trait Singleton {
public static function getInstance() { ... }
}
class A {
use Singleton;
// ...
}
class B extends ArrayObject {
use Singleton;
// ...
}
// Beide Klassen verwenden nun das Singleton Trait und implementieren somit das Singleton-Pattern:
A::getInstance();
B::getInstance();
Es wird noch besser: Wie bereits erwähnt, kann eine Klasse kann beliebig viele Traits verwenden. Da stellt sich der aufgeweckte Coder natürlich die Frage:
Was passiert bei Konflikten?
Sprich: Was passiert, wenn zwei Traits verwenden werden, die beide eine Methode mit der selben Signatur definieren?
trait A {
public function foo() {
echo 'a';
}
public function bar() {
echo 'A';
}
}
trait B {
public function foo() {
echo 'b';
}
public function bar() {
echo 'B';
}
}
class C {
use A, B;
}
Dazu ist folgeneds zu sagen: Traits werden bereits in einigen Sprachen verwendet und es hat sich gezeigt, dass Konflikte zwar auftreten aber das eher die Ausnahme darstellt. Dennoch muss es natürlich ein definiertes Verhalten geben, das vorschreibt, was passieren soll, wenn Konflikte auftreten.
Diese Konfliktlösung sieht hier wie folgt aus:
Erstmal wirft PHP eine Warning um dem Entwickler darauf aufmerksam zu machen, dass ein Konflikt aufgetreten ist. Und gibt dazu auch die Info, wo der Konflikt genau auftritt. In dem Fall würde es die beiden Methoden foo() und bar() melden.
Und das ist auch gut so, denn keine der beiden Methoden werden in Klasse C zur Verfügung stehen! Richtig, die Konfliktlösung sieht vor, dass alles, was einen Konflikt erzeugt, rausfliegt.
PHP zwingt uns damit, die Traits ordentlich zu verwenden und PHP zu sagen, was wir aus welchem Trait haben wollen:
class C {
use A, B {
B::foo instead A;
A::bar instead B;
}
}
?>
Dieser Code bewirkt folgendes Verhalten: Klasse C erhält aus Trait B die Methode foo() und aus Trait A die Methode bar().
Entsprechend würde ein Aufruf der beiden Methoden auf Klasse C “b” und “A” ausgeben.
Das ist zwar cool, aber dennoch nicht die sauberste Lösung. Es gibt Alternativen: So kann der Entwickler auch Aliase vergeben:
class C {
use A, B {
B::foo instead A;
A::bar instead B;
B::bar as bar2;
}
}
Ok, ich gebe zu, dass sich die Beispiele jetzt nicht gerade durch Kreativität auszeichen, aber solange man erkennen kann um was es geht, reicht das
Klasse C würde nach diesem Beispiel nun zusätzlich eine Methode bar2() besitzen, welche der bar()-Methode von Trait B entspricht.
Fazit
Kombiniert man die OOP und ihre Features (Vererbung, Interfaces, Namespaces, Kapselung) nun mit den Traits kann man problemlos PHP-Anwendungen implementieren, die streng dem DRY-Prinzip folgen und gleichzeitg eine konzeptionell saubere Klassen-Hierarchie besitzen.
Es gibt hierzu noch ein wenig mehr zu sagen, aber das ist erstmal das Wichtigste. Alles Weitere kann ich gerne noch in einen zweiten Artikel erklären
over and out


IchBinIch says:
Wow, das finde ich mal richtig cool und freue mich darauf, damit zu arbeiten! =)
Leider wird es wahrscheinlich noch sehr lange dauern! =(
Unser Server läuft immer noch mit 5.2, ich träume also erst mal weiter vone Namespaces und Co …
Ach, vlt. stellst du noch die Farben für die Kommentare noch richtig ein, graue Schriffarbe auf graumen Hintergrund ist echt schwer zu lesen/schreiben!
Benny says:
Ohje, das war wirklich suboptimal … direkt mal geändert. Danke für den Hinweis
Wenn man an ältere PHP-Versionen gebunden ist, ist das tatsächlich immer etwas demotivierend, wenn man die tollen neuen Features sieht. Ist aber mit fast aller Art von Software so.
Da hilft nur Warten
Schei? Codierung? › Dein IT Blog says:
[...] PHP 5.4 Feautre: Züge – horizontale Wiederverwenden von code [...]
Viel Wind um Traits – was soll das alles? | codenaschereien.de says:
[...] Es ist nicht noch nicht lange her, da erschien die neue Beta 2 der PHP-Version 5.4. Diese beinhaltet die mittlerweile doch schon an einigen Stellen im Internet diskustierten Traits. Grund genug, damit ich mir die Sache auch einmal ansehe und aus meiner Perspektive beleuchte. Und nein, ich bringe nicht das Singleton-Beispiel. Dieser Artikel soll auch nicht die Funktionsweise von Traits erklären, sondern deren Sinnhaftigkeit und Anwendung diskutieren. Wer sich mit dem Thema Traits bisher noch nicht beschäftigt hat, ist deshalb mit dieser kleinen Einführung gut bedient: http://blog.itws.de/578/php-5-4-feautre-traits-horizontaler-code-reuse/ [...]