Rozwiązywanie konfliktów metod traitów w OOP w PHP
Ponieważ jedna klasa może używać kilku traitów, może nas spotkać problem, który powstaje, gdy dwa traity mają metody o tej samej nazwie.
W tym przypadku PHP zwróci błąd fatalny. Aby naprawić sytuację, konieczne będzie jawne rozwiązanie konfliktu nazw. Jak to się robi - zobaczymy w praktyce.
Załóżmy, że mamy dwa traity z identyczną
metodą method:
<?php
trait Trait1
{
private function method()
{
return 1;
}
}
trait Trait2
{
private function method()
{
return 2;
}
}
?>
Załóżmy również, że mamy klasę Test,
używającą obu naszych traitów. Jeśli po prostu
podłączymy oba traity do naszej klasy,
PHP zwróci błąd, ponieważ traity mają
zbieżne metody:
<?php
// Ten kod zwróci błąd!
class Test
{
use Trait1, Trait2; // podłączamy traity
}
?>
Rozwiążmy konflikt nazw
naszych traitów. Służy do tego specjalny
operator insteadof. Za pomocą tego operatora
będziemy używać metody method traita
Trait1 zamiast takiej samej metody traita
Trait2:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
}
new Test;
?>
Jak widzicie, składnia jest następująca: najpierw
nazwa traita, potem dwa dwukropki, potem nazwa
metody, potem nasz operator insteadof
i nazwa drugiego traita.
Sprawdźmy:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
public function __construct()
{
echo $this->method(); // wyświetli 1, bo to metoda pierwszego traita
}
}
new Test;
?>
A więc, w naszej klasie powiedzieliśmy, że jeśli
używana jest metoda method, to należy
brać ją z pierwszego traita. Można i odwrotnie
- wziąć metodę drugiego traita:
<?php
class Test
{
use Trait1, Trait2 {
Trait2::method insteadof Trait1;
}
public function __construct()
{
echo $this->method(); // wyświetli 2, bo to metoda drugiego traita
}
}
new Test;
?>
W każdym przypadku, jeśli wskażemy użycie
metody jednego traita, to metoda drugiego traita
staje się niedostępna. Można użyć
i metody drugiego traita, zmieniając jej nazwę
poprzez słowo kluczowe as, w ten sposób:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method() + $this->method2(); // wyświetli 3
}
}
new Test;
?>
W razie potrzeby można zmienić nazwę i metody pierwszego traita:
<?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(); // wyświetli 3
}
}
new Test;
?>
Użycie słowa kluczowego as bez
zdefiniowania metody głównej poprzez insteadof
jest niemożliwe, spowoduje to błąd:
<?php
// Ta klasa zwróci błąd:
class Test
{
use Trait1, Trait2 {
Trait1::method as method1;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method1() + $this->method2();
}
}
new Test;
?>
Stwórz 3 traity o nazwach Trait1,
Trait2 i Trait3. Niech w pierwszym
traicie będzie metoda method, zwracająca
1, w drugim traicie - jednomonimiczna
metoda, zwracająca 2, a w trzecim
traicie - jednomonimiczna metoda,
zwracająca 3.
Stwórz klasę Test, używającą
wszystkich trzech stworzonych przez nas traitów. Stwórz w
tej klasie metodę getSum, zwracającą
sumę wyników metod podłączonych traitów.