Resumo : neste tutorial, você aprenderá como usar características do PHP para compartilhar funcionalidades entre classes independentes, que não estão na mesma hierarquia de herança.
Introdução às características do PHP
A reutilização de código é um dos aspectos mais importantes da programação orientada a objetos. No PHP, você usa herança para permitir a reutilização de código em diferentes classes com a mesma hierarquia de herança.
Para conseguir a reutilização de código, você move a funcionalidade comum das classes para métodos da classe pai. No entanto, a herança torna o código fortemente acoplado. Portanto, o uso excessivo da herança pode dificultar a manutenção do código.
Para superar esse problema, o PHP 5.4 introduziu uma nova unidade de código reutilizável chamada trait
. As características permitem reutilizar vários métodos livremente em muitas classes diferentes que não precisam estar na mesma hierarquia de classes.
A herança permite que as classes reutilizem o código verticalmente, enquanto as características permitem que as classes reutilizem o código horizontalmente.
Uma característica é semelhante a uma classe, mas serve apenas para agrupar métodos de maneira refinada e consistente. O PHP não permite que você crie uma instância de um Trait como uma instância de uma classe. E não existe tal conceito de instância de uma característica.
Exemplo de característica PHP
Para definir uma característica, você usa a palavra-chave trait seguida de um nome da seguinte maneira:
<?php
trait Logger
{
public function log($msg)
{
echo '<pre>';
echo date('Y-m-d h:i:s') . ':' . '(' . __CLASS__ . ') ' . $msg . '<br/>';
echo '</pre>';
}
}
Linguagem de código: HTML, XML ( xml )
Para usar uma característica em uma classe, você usa a use
palavra-chave. Todos os métodos da característica estão disponíveis na classe onde ela é utilizada. Chamar um método de uma característica é semelhante a chamar um método de instância.
O exemplo a seguir demonstra como usar o Logger
trait na BankAccount
classe:
class BankAccount
{
use Logger;
private $accountNumber;
public function __construct($accountNumber)
{
$this->accountNumber = $accountNumber;
$this->log("A new $accountNumber bank account created");
}
}
Linguagem de código: PHP ( php )
E você pode reutilizar a Logger
característica na User
classe da seguinte maneira:
class User
{
use Logger;
public function __construct()
{
$this->log('A new user created');
}
}
Linguagem de código: PHP ( php )
Ambas BankAccount
as User
classes e reutilizam métodos da Logger
característica, o que é muito flexível.
Usando múltiplas características
Uma classe pode usar várias características. O exemplo a seguir demonstra como usar várias características na classe IDE. Ele simula o modelo de compilação C em PHP para fins de demonstração.
<?php
trait Preprocessor
{
public function preprocess()
{
echo 'Preprocess...done' . '<br/>';
}
}
trait Compiler
{
public function compile()
{
echo 'Compile code... done' . '<br/>';
}
}
trait Assembler
{
public function createObjCode()
{
echo 'Create the object code files... done.' . '<br/>';
}
}
trait Linker
{
public function createExec()
{
echo 'Create the executable file...done' . '<br/>';
}
}
class IDE
{
use Preprocessor, Compiler, Assembler, Linker;
public function run()
{
$this->preprocess();
$this->compile();
$this->createObjCode();
$this->createExec();
echo 'Execute the file...done' . '<br/>';
}
}
$ide = new IDE();
$ide->run();
Linguagem de código: HTML, XML ( xml )
Compondo múltiplas características
PHP permite compor múltiplas características em uma característica usando a use
instrução na declaração da característica. Por exemplo:
<?php
trait Reader
{
public function read($source)
{
echo sprintf('Read from %s <br>', $source);
}
}
trait Writer
{
public function write($destination)
{
echo sprintf('Write to %s <br>', $destination);
}
}
trait Copier
{
use Reader, Writer;
public function copy($source, $destination)
{
$this->read($source);
$this->write($destination);
}
}
class FileUtil
{
use Copier;
public function copyFile($source, $destination)
{
$this->copy($source, $destination);
}
}
Linguagem de código: HTML, XML ( xml )
Como funciona.
- Primeiro, defina
Reader
eWriter
trate. - Em segundo lugar, defina uma nova característica chamada
Copier
que seja composta por característicasReader
eWriter
. Nocopy()
método daCopier
característica, chame os métodosread()
ewrite()
das característicasReader
eWriter
. - Terceiro, use a
Copier
característica nocopyFile()
método daFileUtil
classe para simular a cópia do arquivo.
Resolução de conflitos de métodos do trait PHP
Substituindo o método de característica
Quando uma classe usa múltiplas características que compartilham o mesmo nome de método, o PHP irá gerar um erro fatal.
Felizmente, você pode instruir o PHP a usar o método usando a inteadof
palavra-chave. Por exemplo:
<?php
trait FileLogger
{
public function log($msg)
{
echo 'File Logger ' . date('Y-m-d h:i:s') . ':' . $msg . '<br/>';
}
}
trait DatabaseLogger
{
public function log($msg)
{
echo 'Database Logger ' . date('Y-m-d h:i:s') . ':' . $msg . '<br/>';
}
}
class Logger
{
use FileLogger, DatabaseLogger{
FileLogger::log insteadof DatabaseLogger;
}
}
$logger = new Logger();
$logger->log('this is a test message #1');
$logger->log('this is a test message #2');
Linguagem de código: HTML, XML ( xml )
Ambas FileLogger
as DatabaseLogger
características e têm o mesmo log()
método.
Na Logger
classe, resolvemos o conflito de nome do método especificando que o log()
método do FileLogger
trait será usado em vez do DatabaseLogger
‘s.
E se você quiser usar os dois log()
métodos das características FileLogger
e DatabaseLogger
? nesse caso, você pode usar um alias para o método da característica dentro da classe que usa a característica.
Método de traço de alias
Ao usar aliases para o mesmo nome de método de múltiplas características, você pode reutilizar todos os métodos nessas características.
Você usa a as
palavra-chave para alias de um método de uma característica a um nome diferente dentro da classe que usa a característica.
O exemplo a seguir ilustra como criar um alias para o método trait para resolver o conflito de nome do método:
class Logger
{
use FileLogger, DatabaseLogger{
DatabaseLogger::log as logToDatabase;
FileLogger::log insteadof DatabaseLogger;
}
}
$logger = new Logger();
$logger->log('this is a test message #1');
$logger->logToDatabase('this is a test message #2');
Linguagem de código: PHP ( php )
O método log()
da DatabaseLogger
classe possui um novo nome ( logToDatabase
) no contexto da Logger
classe.
Neste tutorial, você aprendeu como usar características do PHP para reutilizar o código fora de uma hierarquia de classes.