PHP-traits: methoden delen tussen klassen zonder overerving

PHP-traits: methoden delen tussen klassen zonder overerving

Met PHP 5.4 kwam er een nieuwe constructie in de taal: de “trait”. Dankzij traits konden PHP-klassen eindelijk methoden en properties uit meerdere bronnen overnemen. Een direct antwoord op het probleem van de enkelvoudige overerving.

Hier is een voorbeeld:

php
<?php

trait PersonTrait
{

}

Zoals je ziet lijkt een trait sterk op een klasse. Alleen wordt hij gedeclareerd met het sleutelwoord trait. Er bestaat een naamgevingsconventie voor traits: zet er het achtervoegsel Trait achter. Houd die conventie aan wanneer je zelf traits schrijft, dan blijft de structuur duidelijk.

Anders dan een klasse, en dat is het punt om te onthouden, kan een trait niets extenden of implementeren. Je kunt een trait ook niet instantiëren. Ze bestaan alleen om onze klassen aan te vullen, niet om ze te vervangen.

Traits kunnen methoden hebben, net als klassen. Stel je een klasse Person voor.

php
<?php
abstract class Person
{

}

Onze klasse Person is een abstracte klasse. Dat betekent dat hij bedoeld is om te worden geëxtend door andere klassen die personen voorstellen.

Stel nu dat we een methode fireball() willen toevoegen. We willen vuurballen kunnen gooien, voor de magie. Dan zouden we zoiets kunnen toevoegen.

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

Het probleem is dat je niet wilt dat iedereen een vuurbal kan afvuren, en daar komen de traits in beeld.

Traits zijn perfect om methoden aan een object toe te voegen. We willen een trait geven aan de mensen met magische krachten, dus wat we zoeken is een PowerTrait.

php
<?php

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

We hebben de methode fireball() naar de trait verplaatst. Verder verandert er niets. Dat betekent dat we de methode ook uit Person kunnen halen, zo.

php
<?php
abstract class Animal
{

}

Laten we een klasse Elfe maken die van Person erft.

php
class Elfe extends Person
{
    private $name="Legolas"; // Ja ik weet het, Legolas gooit geen vuurballen, maar hij was de enige die me te binnen schoot...
}

We hebben de klasse Elfe geëxtend, ook al is hij voorlopig leeg. Stel dat elfen kunnen toveren, dan gaan we verder en gebruiken we de trait PowerTrait.

php
<?php

class Elfe extends Person
{
    use PowerTrait;

private $name="Legolas";
}

Het sleutelwoord om een trait aan een klasse toe te voegen is use, door de declaratie use PowerTrait; in de klasse te zetten.

Laten we de methode uitproberen die we van onze trait krijgen.

php
<?php

// Een nieuwe rode panda aanmaken.
$legolas = new Elfe;

// De panda aaien.
$legolas->fireball();

We hebben hier maar één trait gebruikt, maar je kunt er gerust zoveel gebruiken als je nodig hebt. Het volgende kan bijvoorbeeld prima.

php
<?php

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

private $name="Legolas";
}

Gebruik traits om de functionaliteit van je klassen uit te breiden. Ze werken uiteraard alleen op PHP >= 5.4, dus houd daar rekening mee.

Voorrang

Misschien vraag je je nu het volgende af. Wat gebeurt er als we een klasse extenden en tegelijk een trait gebruiken met een methode van dezelfde naam?

Kijk bijvoorbeeld hiernaar:

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 hebben we een TestTrait en een TestClass. Ze hebben allebei een methode test() die vertelt waar de aanroep vandaan komt.

Tijd om te testen:

php
<?php

class Testing extends TestClass
{
    use TestTrait;
}

$test = new Testing;

$test->test();

We hebben een klasse gemaakt die de klasse TestClass extendt en TestTrait gebruikt. Door de gedeelde methode test() aan te roepen, zien we aan de uitvoer welke van de twee voorrang krijgt. Even proberen.

code
Méthode d'un trait

We zien dat de methode van de trait voorrang krijgt op de methode uit de geërfde klasse.

Dat betekent dat we traits kunnen gebruiken om functionaliteit te overschrijven die uit abstracte klassen komt. Handig om te begrijpen als je met traits aan de slag wilt, en daarom is het ook goed om te weten wanneer je een trait in PHP gebruikt, voor dat antwoord verwijs ik je naar een ander artikel over dit onderwerp.

PHP

Damien Flandrin Webdeveloper sinds 2010, maker van Gekkode en Email Impact. Elk artikel wordt vóór publicatie getest op een echt project. Contact
Nieuwsbrief

Nieuwe tests, tutorials en projecten, per e-mail.

Reproduceerbare tests, geversioneerde code, gedateerde resultaten. Nooit spam.