Résolution des conflits de méthodes de traits en POO en PHP
Comme une classe peut utiliser plusieurs traits, un problème peut survenir lorsque deux traits ont des méthodes homonymes.
Dans ce cas, PHP générera une erreur fatale. Pour corriger la situation, il faudra résoudre le conflit de noms explicitement. Comment cela se fait - voyons-le en pratique.
Supposons que nous ayons deux traits avec la même
méthode method :
<?php
trait Trait1
{
private function method()
{
return 1;
}
}
trait Trait2
{
private function method()
{
return 2;
}
}
?>
Supposons que nous ayons également une classe Test,
utilisant nos deux traits. Si nous connectons simplement
les deux traits à notre classe, alors
PHP générera une erreur, car les traits ont
des méthodes conflictuelles :
<?php
// Ce code générera une erreur !
class Test
{
use Trait1, Trait2; // connecter les traits
}
?>
Résolvons le conflit de noms
de nos traits. Pour cela, il existe un opérateur spécial
insteadof. En utilisant cet opérateur,
nous utiliserons la méthode method du trait
Trait1 au lieu de la méthode du même nom du trait
Trait2 :
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
}
new Test;
?>
Comme vous le voyez, la syntaxe est la suivante : d'abord
le nom du trait, puis deux deux-points, puis le nom
de la méthode, puis notre opérateur insteadof
et le nom du second trait.
Vérifions :
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
public function __construct()
{
echo $this->method(); // affichera 1, car c'est la méthode du premier trait
}
}
new Test;
?>
Ainsi, dans notre classe, nous avons dit que si
la méthode method est utilisée, alors il faut
la prendre du premier trait. On peut aussi faire l'inverse
- prendre la méthode du second trait :
<?php
class Test
{
use Trait1, Trait2 {
Trait2::method insteadof Trait1;
}
public function __construct()
{
echo $this->method(); // affichera 2, car c'est la méthode du second trait
}
}
new Test;
?>
Dans tous les cas, si nous spécifions d'utiliser
la méthode d'un trait, alors la méthode du second trait
devient inaccessible. On peut aussi utiliser
la méthode du second trait, en la renommant
via le mot-clé as, comme ceci :
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method() + $this->method2(); // affichera 3
}
}
new Test;
?>
Si on le souhaite, on peut aussi renommer la méthode du premier 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(); // affichera 3
}
}
new Test;
?>
Utiliser le mot-clé as sans
définir la méthode principale via insteadof
est interdit, cela générera une erreur :
<?php
// Cette classe générera une erreur :
class Test
{
use Trait1, Trait2 {
Trait1::method as method1;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method1() + $this->method2();
}
}
new Test;
?>
Créez 3 traits avec les noms Trait1,
Trait2 et Trait3. Que le premier
trait ait une méthode method renvoyant
1, le second trait - une méthode homonyme
renvoyant 2, et le troisième
trait - une méthode homonyme
renvoyant 3.
Créez une classe Test utilisant
les trois traits que nous avons créés. Créez dans
cette classe une méthode getSum renvoyant
la somme des résultats des méthodes des traits connectés.