Propósito geral dos Traits
A Orientação a Objetos em PHP, não trabalha com conceitos de herança múltipla. Apesar da herança múltipla não fazer falta alguma em PHP(ou em qualquer outra linguagem), por trazer consigo mais desvantagens do que vantagens, como implementações difíceis, manutenção trabalhosa, acoplamento forte, baixa coesão e centenas de outros problemas, há ainda assim, a necessidade de se reutilizar recursos em diferentes locais, evitando rescrever trechos repetidos de códigos.
Traits são mecanismos que possibilitam o reuso de código, em um contexto relacional não vertical. Com traits, em uma única classe é possível utilizar recursos que se tornam modulares e que são carregados conforme necessidade. A vantagem de utilizar Traits, vai além da reutilização e, o grande destaque está em seu relacionamento com outros participantes que, ao contrário da herança, não tem o relacionamento “É UM” e sim um talvez, se “COMPORTA(-SE) COMO”. Essa sútil diferença é de suma importância, evitando os problemas citados anteriormente quando se faz o uso indiscriminado e / ou incorreto de uma ou muitas extensões(o qual já foi citado não ser suportado no PHP), evitando-se relacionamentos excêntricos, “É UM”, onde por exemplo uma classe Pessoa estende Database, formando o relacionamento Pessoa É UM Database, quando Pessoa, obviamente, não É UM Database.
Um exemplo simples para introduzir a sintaxe em torno das Traits:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
Traits assemelham-se às classes, mais aproximadamente às classes abstratas, que não podem ser instanciadas diretamente, todavia, seu principal objetivo é de reunir grupo(s) de comportamentos(s) que serão reutilizadas em um ou diversos pontos.
Visão mais ampla
Um outro exemplo recorrente, ajuda a ilustrar melhor o propósito de Traits:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
Nesse exemplo, tanto a classe DatabaseLoader, como FileLoader, se comportam como Singleton, e por ambas herdarem esse comportamento, não é possível(devido aos construtores protegidos) criar novos objetos dessas:
1 2 |
|
1 2 |
|
As classes DatabaseLoader e FileLoader tem comportamentos idênticos à Trait Singleton, portanto, para o efeito desejado o correto será:
1 2 3 4 5 6 7 8 9 10 11 |
|
Isso reforça a grande cartada de Traits – possibilitar comportamentos aos participantes, ou seja, relacionamentos do tipo comporta-se como. A leitura dessas classes seria algo adjacente a: DatabaseLoader e FileLoader não são Singletons, não tem Singletons(usar singleton não é um contrato), mas se comportam como Singletons.
Futuramente, tanto DatabaseLoader como FileLoader, de maneira flexivelmente simples, poderiam deixar de se comportar como Singletons, apenas deixando de usar(se comportar como) Trait Singleton.
Traits e Interface
Um exemplo usando Traits e Contrato:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
|
Há alguns pontos a serem ressaltados, por exemplo, como é notado, as classes PDFReaderFile e CSVReaderFile tem (uma interface) um ReaderFile, mas cada um se comporta(uma trait) de uma maneira. Nesse caso também, foi possível realizar uma abstração encapsulada, pois, quem usa a classe LoaderContents, não tem conhecimentos de que o contrato assinado está sob comportamentos ou uma implementação.
Os construtores de cada Traits são herdados, tendo os construtores dos participantes que usam essas Traits, os mesmos comportamentos.
Traits e Autload
Também é possível utilizar Traits com autoload/spl_autload_register e a função trait_exists():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Conclusão final
Há uma infinidade de maneiras de se usar Traits, como compor Traits dentro de Traits, criando uma hierarquia de comportamentos. Sem dúvida, Traits trouxe para o PHP muito mais flexibilidade em todos os sentidos.