Resolução de conflitos de métodos de traits na OOP em PHP
Como uma classe pode usar várias traits, podemos enfrentar um problema que surge quando duas traits possuem métodos com o mesmo nome.
Nesse caso, o PHP emitirá um erro fatal. Para corrigir a situação, será necessário resolver o conflito de nomes explicitamente. Como isso é feito - veremos na prática.
Suponha que temos duas traits com o mesmo
método method:
<?php
trait Trait1
{
private function method()
{
return 1;
}
}
trait Trait2
{
private function method()
{
return 2;
}
}
?>
Suponha que também tenhamos uma classe Test,
usando ambas as nossas traits. Se simplesmente
conectarmos ambas as traits à nossa classe, o
PHP emitirá um erro, pois as traits possuem
métodos conflitantes:
<?php
// Este código emitirá um erro!
class Test
{
use Trait1, Trait2; // conectando as traits
}
?>
Vamos resolver o conflito de nomes
de nossas traits. Para isso, existe um operador
especial insteadof. Usando este operador,
utilizaremos o método method da trait
Trait1 em vez do método homônimo da trait
Trait2:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
}
new Test;
?>
Como você pode ver, a sintaxe é a seguinte: primeiro
o nome da trait, depois dois pontos, depois o nome
do método, depois nosso operador insteadof
e o nome da segunda trait.
Vamos testar:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
public function __construct()
{
echo $this->method(); // exibirá 1, pois é o método da primeira trait
}
}
new Test;
?>
Então, em nossa classe, dissemos que se
o método method for usado, ele deve
ser obtido da primeira trait. Também podemos fazer o contrário
- usar o método da segunda trait:
<?php
class Test
{
use Trait1, Trait2 {
Trait2::method insteadof Trait1;
}
public function __construct()
{
echo $this->method(); // exibirá 2, pois é o método da segunda trait
}
}
new Test;
?>
De qualquer forma, se especificarmos o uso do
método de uma trait, o método da segunda trait
torna-se inacessível. Podemos usar
o método da segunda trait renomeando-o
usando a palavra-chave as, assim:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method() + $this->method2(); // exibirá 3
}
}
new Test;
?>
Se desejar, também pode renomear o método da primeira trait:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
Trait1::method as method1;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method1() + $this->method2(); // exibirá 3
}
}
new Test;
?>
Não é possível usar a palavra-chave as sem
definir o método principal via insteadof,
isso emitirá um erro:
<?php
// Esta classe emitirá um erro:
class Test
{
use Trait1, Trait2 {
Trait1::method as method1;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method1() + $this->method2();
}
}
new Test;
?>
Crie 3 traits com os nomes Trait1,
Trait2 e Trait3. Deixe no primeiro
trait um método method retornando
1, no segundo trait - um método homônimo
retornando 2, e no terceiro
trait - um método homônimo
retornando 3.
Crie uma classe Test usando
todas as três traits que criamos. Crie neste
classe um método getSum retornando
a soma dos resultados dos métodos das traits conectadas.