Traits em PHP. Herança Horizontal

Post revisitado em junho/2014. Tudo que está aí funciona na versão atual PHP 5.5.x. Enjoy 😉

Antevejo que no futuro, o PHP como uma linguagem iterativa e incremental que é, adicionará ao seu núcleo um recurso muito valioso na categoria orientação à objetos.Antevejo ele, os Traits. E mais, consigo prever que será algo assim:

ola()} trait !";
}
}

$ola = new Mundo();
$ola->world();
// Olá trait !

Ok, não sou bidu. Realmente os Traits estão na lista do possível-futuro PHP 5.4 e eu, baixei a build de 31/03/2011 para testar.

Traits

O PHP não suporta herença multipla – amém – e por este motivo, às vezes ficamos limitados em algumas decisões de projeto (design). O maior problema neste ponto é que toda herença até agora (PHP 5.3.x) é vertical, ou seja, se eu precisar de um nível de abstração diferente no meio do processo, ou precisarei adicionar a nova abstração e reescrever tudo abaixo dela, ou ainda, terei que duplicar o código pois não conseguirei satisfazer a herença.

É nesse ponto que os Traits aparecem. Diferentemente da herença (vertical), os Traits possibilitam-nos criar herenças horizontais.

Exemplo, dada a necessidade: haverão Funcionários, Supervisores, Gestores e Diretores no sistema e estes possui em comum o fato de receber salário. (capitalismo). Uma possibilidade seria:

Pessoa > Funcionario
Pessoa > Supervisores
Pessoa > Gestores
Pessoa > Diretores

Tudo perfeito. Porém, chega outra necessidade: Gestores e Diretores tem a capacidade de demitir. Gestores precisam gerenciar cronogramas, assim como os Supervisores fazem.

Pessoa.demitir(pessoa) não faz sentido, pois afetiria todos.
Gestor.demitir(pessoa) e Diretor.demitir(pessoa) atende, mas duplicaria o código.

Pessoa > Supervisor > Gestor
Pessoa > Diretor

Shi, apareceu outro nível hierarquico. Traits auxilia exatamente neste ponto ! Vejamos:

Trait Cronograma

Trait Evil (que contém recursos para demitir uma pessoa)

Pessoa > Funcionario

Pessoa > Supervisor : Cronograma

Pessoa > Gestor : Cronograma : Evil

Pessoa > Diretor : Evil

Note que o Pessoa > Supervisor : Cronograma – os dois pontos para indicar o Trait são de minha autoria – era o Pessoa > Supervisor antigo. Isso porque as atribuições para gerenciar cronogramas foram passadas para o Trait.

Neste pequeno exemplo, o Trait nos auxiliou com um problema de domínio. Acredito que ele também aplique-se e muito bem para problemas onde temos domínios transversais, pois, nele ficariam as atividades do outro domínio pode o domínio principal teria acesso aos recursos sem quebrar a SRP.

Traits em PHP

Como disse no começo, o futuro-provável PHP 5.4 virá com o Trait. Por enquanto essa implementação funcionaria:

definirPressao(self::$ATRASADO);
        $this->youTube();
    }

    private function youTube() {

    }
}

class Funcionario extends Pessoa {
}

class Supervisor extends Pessoa {
    use Cronograma;
}

$colaborador = new Funcionario();
$controlador = new Supervisor();
$controlador->cobrarDe($colaborador);

Os Traits possuem boas capacidades com métodos de instância e estáticos. Vamos explorar um pouco mais:

sayHello();
$view->sayWorld();
// exibe: Olá Mundo

Pegando informações da Classe

eu();
// exibe: Foo

Usando Variáveis de instância da classe:

hello} world";
    }
}

class Hello {
    private $hello = "Hello";
    use World;
}

$hello = new Hello();
echo $hello->help();
// exibe: Hello world

Modificadores de acesso dos traits na classe

ola();
// Fatal Error....

Modificadores de acesso com alias para nome de método

aloha();
// Olá mundo

Há outros vários recursos como métodos abstratos nos Traits, precedência, métodos estáticos, late static bindings, métodos mágicos, alias para nome de método do Trait ao usá-lo na classe. Para Rubistas ou Scalistas (?) as possibilidades são as mesmas dos Mixins e Traits de Ruby e Scala respectivamente.

RFC do PHP Trait
PHP doc do Trait. PHP >= 5.4

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s