PHP Traits: Code über mehrere Klassen hinweg wiederverwenden

PHP Traits: Code über mehrere Klassen hinweg wiederverwenden

Mit PHP 5.4 kam ein neues Sprachkonstrukt hinzu: das „Trait“. Über Traits konnten PHP-Klassen von da an Methoden und Eigenschaften aus mehreren Quellen erben. Eine direkte Antwort auf das Problem der einfachen Vererbung.

Hier ein Beispiel:

php
<?php

trait PersonTrait
{

}

Wie du siehst, ähnelt ein Trait stark einer Klasse. Deklariert wird es allerdings mit dem Schlüsselwort trait. Für Traits gilt eine Namenskonvention: das Suffix Trait anhängen. Halte dich daran, wenn du eigene Traits schreibst, dann bleibt die Struktur übersichtlich.

Anders als bei einer Klasse gilt: Ein Trait lässt sich weder erweitern noch implementieren. Instanzieren kannst du es ebenso wenig. Traits haben nur einen Zweck, nämlich unsere Klassen zu ergänzen, nicht sie zu ersetzen.

Traits können Methoden haben, genau wie Klassen. Stell dir eine Klasse Person vor.

php
<?php
abstract class Person
{

}

Unsere Klasse Person ist abstrakt. Sie ist also dazu da, von anderen Klassen erweitert zu werden, die Personen darstellen.

Nimm an, wir wollen eine Methode fireball() ergänzen, um Feuerbälle zu werfen und damit zu zaubern. Dann könnten wir etwa Folgendes schreiben.

php
<?php
abstract class Person
{
    public function fireball()
    {
        echo 'This Person send a fireball';
    }
}

Das Problem: Nicht alle sollen einen Feuerball werfen können. Genau hier kommen die Traits ins Spiel.

Traits eignen sich hervorragend dafür, einem Objekt Methoden mitzugeben. Wir wollen den Menschen mit magischen Kräften ein Trait mitgeben, gesucht ist also ein PowerTrait.

php
<?php

trait PowerTrait
{
    public function fireball()
    {
        echo 'This person send a fireball.';
    }
}

Wir haben die Methode fireball() in das Trait verschoben. Einen weiteren Unterschied findest du hier nicht. Damit können wir die Methode auch aus Person entfernen, so:

php
<?php
abstract class Animal
{

}

Legen wir eine Klasse Elfe an, die von Person erbt.

php
class Elfe extends Person
{
    private $name="Legolas"; // Ja, ich weiß, Legolas wirft keine Feuerbälle, aber mir fiel nur er ein …
}

Wir haben die Klasse Elfe abgeleitet, auch wenn sie vorerst leer ist. Nehmen wir an, Elfen können zaubern: Dann binden wir das Trait PowerTrait ein.

php
<?php

class Elfe extends Person
{
    use PowerTrait;

private $name="Legolas";
}

Das Schlüsselwort, mit dem du einer Klasse ein Trait mitgibst, ist use, du schreibst die Deklaration use PowerTrait; in die Klasse.

Probieren wir die geerbte Methode aus unserem Trait aus.

php
<?php

// Einen neuen Roten Panda anlegen.
$legolas = new Elfe;

// Den Panda streicheln.
$legolas->fireball();

Bisher haben wir nur ein einziges Trait eingesetzt, aber du kannst so viele verwenden, wie du brauchst. Folgendes ist zum Beispiel möglich.

php
<?php

class Elfe extends Person
{
    use PlayerTrait;
    use PowerTrait;
    use AttributTrait;

private $name="Legolas";
}

Nutze Traits, um deine Klassen funktional zu erweitern. Sie stehen dir natürlich erst ab PHP >= 5.4 zur Verfügung, behalte das im Hinterkopf.

Vorrang

Vielleicht fragst du dich Folgendes: Was passiert, wenn wir eine Klasse erweitern und dabei ein Trait mit einer gleichnamigen Methode einbinden?

Sieh dir das an:

php
<?php
trait TestTrait
{
    public function test()
    {
        echo 'Méthode d\'un trait';
    }
}

class TestClass
{
    public function test()
    {
        echo 'Méthode d\'une classe';
    }
}

Hier haben wir ein TestTrait und eine TestClass. Beide besitzen eine Methode test(), die verrät, woher der Aufruf stammt.

Zeit für den Test:

php
<?php

class Testing extends TestClass
{
    use TestTrait;
}

$test = new Testing;

$test->test();

Wir haben eine Klasse geschrieben, die die Klasse TestClass erweitert und TestTrait einbindet. Über den Aufruf der gemeinsamen Methode test() erkennen wir an der Ausgabe, welche von beiden Vorrang hat. Probieren wir es aus.

code
Méthode d'un trait

Wir sehen: Die Methode des Traits hat Vorrang vor der Methode aus der geerbten Klasse.

Das heißt, wir können mit Traits die geerbte Funktionalität abstrakter Klassen überschreiben. Das ist gut zu wissen, wenn du Traits einsetzen willst. Genauso solltest du wissen, wann ein Trait in PHP sinnvoll ist, dazu liest du am besten den eigenen Artikel zu dieser Frage.

PHP

Damien Flandrin Webentwickler seit 2010, Gründer von Gekkode und Email Impact. Jeder Artikel wird vor der Veröffentlichung an einem echten Projekt getestet. Kontakt
Newsletter

Neue Tests, Tutorials und Projekte, per E-Mail.

Reproduzierbare Tests, versionierter Code, datierte Ergebnisse. Niemals Spam.