Разрешаване на конфликти в методите на трейтове в ООП в PHP
Тъй като един клас може да използва няколко трейта, може да срещнем проблем, който възниква, когато два трейта имат методи с едно и също име.
В този случай PHP ще изведе фатална грешка. За да коригираме ситуацията, ще трябва да разрешим конфликта на имената изрично. Как се прави това - ще видим на практика.
Да предположим, че имаме два трейта с еднакъв
метод method:
<?php
trait Trait1
{
private function method()
{
return 1;
}
}
trait Trait2
{
private function method()
{
return 2;
}
}
?>
Да предположим, че имаме и клас Test,
който използва и двата ни трейта. Ако просто
свържем и двата трейта към нашия клас, то
PHP ще изведе грешка, тъй като трейтовете имат
съвпадащи методи:
<?php
// Този код ще изведе грешка!
class Test
{
use Trait1, Trait2; // свързваме трейтовете
}
?>
Нека разрешим конфликта на имената
на нашите трейтове. За това съществува специален
оператор insteadof. С помощта на този оператор
ще използваме метода method на трейта
Trait1 вместо същия метод на трейта
Trait2:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
}
new Test;
?>
Както виждате, синтаксисът е следният: първо
името на трейта, после две двоеточия, после името
на метода, после нашият оператор insteadof
и името на втория трейт.
Нека проверим:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
public function __construct()
{
echo $this->method(); // ще изведе 1, тъй като това е метод на първия трейт
}
}
new Test;
?>
И така, в нашия клас казахме, че ако
се използва метод method, трябва да
се взема от първия трейт. Може и обратното
- да вземем метода на втория трейт:
<?php
class Test
{
use Trait1, Trait2 {
Trait2::method insteadof Trait1;
}
public function __construct()
{
echo $this->method(); // ще изведе 2, тъй като това е метод на втория трейт
}
}
new Test;
?>
Във всеки случай, ако укажем да използваме
метода на един трейт, то методът на втория трейт
става недостъпен. Може да използваме
и метода на втория трейт, като го преименуваме
чрез ключовата дума as, ето така:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method() + $this->method2(); // ще изведе 3
}
}
new Test;
?>
При желание може да преименувате и метода на първия трейт:
<?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(); // ще изведе 3
}
}
new Test;
?>
Използването на ключовата дума as без
дефиниране на главния метод чрез insteadof
не е позволено, това ще изведе грешка:
<?php
// Този клас ще изведе грешка:
class Test
{
use Trait1, Trait2 {
Trait1::method as method1;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method1() + $this->method2();
}
}
new Test;
?>
Направете 3 трейта с имена Trait1,
Trait2 и Trait3. Нека в първия
трейт има метод method, връщащ
1, във втория трейт - едноименен
метод, връщащ 2, а в третия
трейт - едноименен метод,
връщащ 3.
Направете клас Test, използващ
и трите създадени от нас трейта. Направете в
този клас метод getSum, връщащ
сумата от резултатите на методите на свързаните трейтове.