Resolución de conflictos de métodos de traits en POO en PHP
Dado que una clase puede utilizar varios traits, podemos encontrarnos con un problema que surge cuando dos traits tienen métodos con el mismo nombre.
En este caso, PHP mostrará un error fatal. Para solucionar la situación, será necesario resolver el conflicto de nombres de manera explícita. Cómo se hace - lo veremos en la práctica.
Supongamos que tenemos dos traits con el mismo
método method:
<?php
trait Trait1
{
private function method()
{
return 1;
}
}
trait Trait2
{
private function method()
{
return 2;
}
}
?>
Supongamos también que tenemos una clase Test,
que utiliza ambos traits. Si simplemente
conectamos ambos traits a nuestra clase,
PHP mostrará un error, ya que los traits tienen
métodos coincidentes:
<?php
// ¡Este código dará un error!
class Test
{
use Trait1, Trait2; // conectamos los traits
}
?>
Resolvamos el conflicto de nombres
de nuestros traits. Para ello existe un operador
especial insteadof. Usando este operador
utilizaremos el método method del trait
Trait1 en lugar del método homónimo del trait
Trait2:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
}
new Test;
?>
Como puedes ver, la sintaxis es la siguiente: primero
el nombre del trait, luego dos puntos, luego el nombre
del método, luego nuestro operador insteadof
y el nombre del segundo trait.
Comprobemos:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
public function __construct()
{
echo $this->method(); // mostrará 1, porque es el método del primer trait
}
}
new Test;
?>
Entonces, en nuestra clase hemos dicho que si
se utiliza el método method, se debe
tomar del primer trait. También se puede hacer al revés
- tomar el método del segundo trait:
<?php
class Test
{
use Trait1, Trait2 {
Trait2::method insteadof Trait1;
}
public function __construct()
{
echo $this->method(); // mostrará 2, porque es el método del segundo trait
}
}
new Test;
?>
En cualquier caso, si indicamos que se use
el método de un trait, entonces el método del otro trait
resulta inaccesible. Se puede utilizar
también el método del segundo trait, renombrándolo
mediante la palabra clave as, así:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method() + $this->method2(); // mostrará 3
}
}
new Test;
?>
Si se desea, también se puede renombrar el método del primer 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(); // mostrará 3
}
}
new Test;
?>
No se puede usar la palabra clave as sin
definir el método principal mediante insteadof,
esto dará un error:
<?php
// Esta clase dará un error:
class Test
{
use Trait1, Trait2 {
Trait1::method as method1;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method1() + $this->method2();
}
}
new Test;
?>
Crea 3 traits con los nombres Trait1,
Trait2 y Trait3. Que en el primer
trait haya un método method que devuelva
1, en el segundo trait - un método homónimo
que devuelva 2, y en el tercer
trait - un método homónimo,
que devuelva 3.
Crea una clase Test que utilice
los tres traits que hemos creado. Crea en
esta clase un método getSum que devuelva
la suma de los resultados de los métodos de los traits conectados.