Hantera metodkonflikter i traits i OOP i PHP
Eftersom en klass kan använda flera traits kan vi stöta på ett problem som uppstår när två traits har metoder med samma namn.
I det här fallet kommer PHP att ge ett fatalt fel. För att åtgärda situationen måste vi lösa namnkonflikten explicit. Hur detta görs - låt oss se i praktiken.
Låt oss säga att vi har två traits med samma
metod method:
<?php
trait Trait1
{
private function method()
{
return 1;
}
}
trait Trait2
{
private function method()
{
return 2;
}
}
?>
Låt oss också säga att vi har en klass Test
som använder båda våra traits. Om vi bara
ansluter båda traitsen till vår klass, så
kommer PHP att ge ett fel, eftersom traitsen har
motsvarande metoder:
<?php
// Denna kod kommer att ge ett fel!
class Test
{
use Trait1, Trait2; // ansluter traits
}
?>
Låt oss lösa namnkonflikten
i våra traits. För detta finns en speciell
operator insteadof. Med denna operator
kommer vi att använda metoden method från traitet
Trait1 istället för samma metod från traitet
Trait2:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
}
new Test;
?>
Som du ser är syntaxen följande: först
traitets namn, sedan två kolon, sedan metodens
namn, sedan vår operator insteadof
och namnet på det andra traitet.
Låt oss kolla:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
public function __construct()
{
echo $this->method(); // kommer att visa 1, eftersom det är metoden från det första traitet
}
}
new Test;
?>
Så, i vår klass sa vi att om
metoden method används, bör
den tas från det första traitet. Vi kan göra tvärtom
- ta metoden från det andra traitet:
<?php
class Test
{
use Trait1, Trait2 {
Trait2::method insteadof Trait1;
}
public function __construct()
{
echo $this->method(); // kommer att visa 2, eftersom det är metoden från det andra traitet
}
}
new Test;
?>
I vilket fall som helst, om vi specificerar att vi ska använda
metoden från ett trait, så blir metoden från det andra traitet
otillgänglig. Vi kan använda
metoden från det andra traitet också, genom att byta namn på den
via sökordet as, så här:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method() + $this->method2(); // kommer att visa 3
}
}
new Test;
?>
Om så önskas kan man byta namn på metoden från det första traitet också:
<?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(); // kommer att visa 3
}
}
new Test;
?>
Att använda sökordet as utan
att definiera huvudmetoden via insteadof
går inte, detta kommer att ge ett fel:
<?php
// Denna klass kommer att ge ett fel:
class Test
{
use Trait1, Trait2 {
Trait1::method as method1;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method1() + $this->method2();
}
}
new Test;
?>
Skapa 3 traits med namnen Trait1,
Trait2 och Trait3. Låt det första
traitet ha en metod method som returnerar
1, i det andra traitet - en metod med samma namn
som returnerar 2, och i det tredje
traitet - en metod med samma namn
som returnerar 3.
Skapa en klass Test som använder
alla tre traits vi skapat. Skapa i
denna klass en metod getSum som returnerar
summan av resultaten från metoderna i de anslutna traitsen.