Решавање конфликта метода трејтова у ООП у 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 који враћа збир резултата метода повезаних трејтова.