Traits em PHP: herança múltipla de métodos e prioridade

Traits em PHP: herança múltipla de métodos e prioridade

No PHP 5.4 foi introduzida na linguagem uma construção nova chamada «trait». Com os traits, as classes de PHP passaram a poder herdar métodos e propriedades de várias fontes. Uma resposta direta ao problema da herança simples.

Eis um exemplo:

php
<?php

trait PersonTrait
{

}

Como vês, um trait parece-se muito com uma classe. A diferença é que se declara com a palavra-chave trait. Existe uma convenção de nomes para os traits que consiste em acrescentar o sufixo Trait, segue-a quando criares os teus, para manter uma estrutura clara.

Ao contrário de uma classe, e convém não esquecer, um trait não se pode estender nem implementar. Também não se pode instanciar. O seu único objetivo é enriquecer as nossas classes, não substituí-las.

Os traits podem ter métodos, tal como as classes. Imaginemos uma classe Person.

php
<?php
abstract class Person
{

}

A nossa classe Person é uma classe abstrata. Ou seja, foi pensada para ser estendida por outras classes que representam pessoas.

Suponhamos que queremos acrescentar um método fireball(). Por exemplo, para atirar bolas de fogo e fazer magia. Podíamos escrever algo assim.

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

O problema é que não queres que toda a gente possa atirar uma bola de fogo, e é aqui que os traits entram em jogo.

Os traits são perfeitos para acrescentar métodos a um objeto. Queremos dá-lo aos humanos que têm poderes mágicos, por isso o que procuramos é um PowerTrait

php
<?php

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

Movemos o método fireball() para o trait. Não há mais nenhuma diferença. Isso significa que também podemos retirar o método de Person, assim.

php
<?php
abstract class Animal
{

}

Vamos criar uma classe Elfe que herda de Person.

php
class Elfe extends Person
{
    private $name="Legolas"; // Sim, eu sei que o Legolas não atira bolas de fogo, mas foi o único que me veio à cabeça...
}

Já temos a classe Elfe, ainda que por agora esteja vazia. Imaginemos que os elfos podem lançar feitiços: avancemos e usemos o trait PowerTrait

php
<?php

class Elfe extends Person
{
    use PowerTrait;

private $name="Legolas";
}

A palavra-chave para acrescentar um trait a uma classe é use, colocando a declaração use PowerTrait;

Vamos experimentar o método herdado do trait.

php
<?php

// Criar um novo panda-vermelho.
$legolas = new Elfe;

// Fazer festas ao panda.
$legolas->fireball();

Por agora só usámos um trait, mas podes usar tantos quantos forem precisos. Por exemplo, isto é possível.

php
<?php

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

private $name="Legolas";
}

Usa os traits para enriquecer a funcionalidade das tuas classes. Claro que só os podes usar em PHP >= 5.4, tem isso em conta.

Prioridade

Talvez estejas a fazer a pergunta seguinte. O que acontece se estendermos uma classe e usarmos um trait que tem um método com o mesmo nome?

Vê com este exemplo:

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

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

Aqui temos um TestTrait e uma TestClass. Ambos têm um método test() que indica de onde vem a chamada.

Hora de testar:

php
<?php

class Testing extends TestClass
{
    use TestTrait;
}

$test = new Testing;

$test->test();

Criámos uma classe que estende a TestClass e usa o TestTrait. Ao chamar o método partilhado test(), vemos qual tem prioridade na saída. Vamos comprovar.

code
Méthode d'un trait

vemos que o método do trait tem prioridade sobre o método da classe herdada.

Isso significa que podemos usar traits para substituir a funcionalidade herdada das classes abstratas. É útil perceber isto se pensas usar traits, e convém também saber quando usar um trait em PHP, para responder a essa pergunta, deixo-te outro artigo sobre o tema.

PHP

Damien Flandrin Programador web desde 2010, criador da Gekkode e do Email Impact. Cada artigo é testado num projeto real antes de ser publicado. Contacto
Newsletter

Os novos testes, tutoriais e projetos, por e-mail.

Testes reproduzíveis, código versionado, resultados datados. Nunca spam.