Løsning af trait-metodekonflikter i OOP i PHP
Da en enkelt klasse kan bruge flere traits, kan vi støde på et problem, der opstår, når to traits har metoder med samme navn.
I dette tilfælde vil PHP give en fatal fejl. For at rette situationen skal man løse navnekonflikten eksplicit. Lad os se hvordan det gøres i praksis.
Lad os sige, at vi har to traits med den samme
metode method:
<?php
trait Trait1
{
private function method()
{
return 1;
}
}
trait Trait2
{
private function method()
{
return 2;
}
}
?>
Lad os også sige, at vi har en klasse Test,
der bruger begge vores traits. Hvis man blot
tilslutter begge traits til vores klasse, vil
PHP give en fejl, fordi traits har
overlappende metoder:
<?php
// Denne kode vil give en fejl!
class Test
{
use Trait1, Trait2; // tilslutter traits
}
?>
Lad os løse navnekonflikten mellem
vores traits. Til dette findes en speciel
operator insteadof. Ved hjælp af denne operator
vil vi bruge metoden method fra trait
Trait1 i stedet for den samme metode fra trait
Trait2:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
}
new Test;
?>
Som du kan se, er syntaksen som følger: først
trait-navnet, derefter to koloner, derefter metode-navnet,
derefter vores operator insteadof
og navnet på det andet trait.
Lad os teste:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
public function __construct()
{
echo $this->method(); // vil udskrive 1, da det er metoden fra det første trait
}
}
new Test;
?>
Så i vores klasse har vi sagt, at hvis
metoden method bruges, skal
den tages fra det første trait. Man kan også gøre omvendt
- tage metoden fra det andet trait:
<?php
class Test
{
use Trait1, Trait2 {
Trait2::method insteadof Trait1;
}
public function __construct()
{
echo $this->method(); // vil udskrive 2, da det er metoden fra det andet trait
}
}
new Test;
?>
Uanset hvad, hvis vi angiver, at vi skal bruge
metoden fra et trait, bliver metoden fra det andet trait
utilgængelig. Man kan også bruge
metoden fra det andet trait ved at omdøbe den
via nøgleordet as, sådan her:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method() + $this->method2(); // vil udskrive 3
}
}
new Test;
?>
Hvis man ønsker, kan man også omdøbe metoden fra det første 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(); // vil udskrive 3
}
}
new Test;
?>
Man kan ikke bruge nøgleordet as uden
at definere hovedmetoden via insteadof,
det vil give en fejl:
<?php
// Denne klasse vil give en fejl:
class Test
{
use Trait1, Trait2 {
Trait1::method as method1;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method1() + $this->method2();
}
}
new Test;
?>
Lav 3 traits med navnene Trait1,
Trait2 og Trait3. Lad det første
trait have en metode method, der returnerer
1, det andet trait - en metode med samme navn,
der returnerer 2, og det tredje
trait - en metode med samme navn,
der returnerer 3.
Lav en klasse Test, der bruger
alle tre af vores oprettede traits. Lav i
denne klasse en metode getSum, der returnerer
summen af resultaterne fra metoderne i de tilsluttede traits.