Traittien menetelmäristiriitojen ratkaiseminen OOP:ssa PHP:ssä
Koska yksi luokka voi käyttää useita traitteja, voi meitä odottaa ongelma, joka syntyy, kun kahdella traitilla on samanimiset menetelmät.
Tässä tapauksessa PHP antaa vakavan virheen. Korjataksemme tilanteen, meidän on ratkaistava nimiristiriita eksplisiittisesti. Miten tämä tehdään - katsotaan käytännössä.
Oletetaan, että meillä on kaksi traitia, joilla on sama
menetelmä method:
<?php
trait Trait1
{
private function method()
{
return 1;
}
}
trait Trait2
{
private function method()
{
return 2;
}
}
?>
Oletetaan myös, että meillä on luokka Test,
joka käyttää molempia traittejamme. Jos yksinkertaisesti
liitämme molemmat traitit luokkaamme, niin
PHP antaa virheen, koska traiteilla on
päällekkäisiä menetelmiä:
<?php
// Tämä koodi antaa virheen!
class Test
{
use Trait1, Trait2; // liitetään traitit
}
?>
Ratkaistaan traittiemme nimiristiriita.
Tätä varten on olemassa erityinen
operaattori insteadof. Tämän operaattorin avulla
käytämme traitin Trait1 menetelmää method
saman menetelmän sijasta traitissa
Trait2:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
}
new Test;
?>
Kuten näette, syntaksi on seuraava: aluksi
traitin nimi, sitten kaksi kaksoispistettä, sitten menetelmän nimi, sitten operaattorimme insteadof
ja toisen traitin nimi.
Testataan:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
public function __construct()
{
echo $this->method(); // tulostaa 1, koska tämä on ensimmäisen traitin menetelmä
}
}
new Test;
?>
Joten, luokassamme sanoimme, että jos
käytetään menetelmää method, tulee
ottaa se ensimmäisestä traitista. Voimme tehdä myös päinvastoin
- ottaa toisen traitin menetelmän:
<?php
class Test
{
use Trait1, Trait2 {
Trait2::method insteadof Trait1;
}
public function __construct()
{
echo $this->method(); // tulostaa 2, koska tämä on toisen traitin menetelmä
}
}
new Test;
?>
Joka tapauksessa, jos määritämme käytettäväksi
yhden traitin menetelmän, niin toisen traitin menetelmä
ei ole käytettävissä. Voimme kuitenkin käyttää
myös toisen traitin menetelmää, nimeämällä sen uudelleen
avainsanalla as, näin:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method() + $this->method2(); // tulostaa 3
}
}
new Test;
?>
Halutessamme voimme nimetä uudelleen myös ensimmäisen traitin menetelmän:
<?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(); // tulostaa 3
}
}
new Test;
?>
Avainsanan as käyttäminen ilman
päämenetelmän määrittelyä insteadof:lla
ei ole sallittua, se aiheuttaa virheen:
<?php
// Tämä luokka antaa virheen:
class Test
{
use Trait1, Trait2 {
Trait1::method as method1;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method1() + $this->method2();
}
}
new Test;
?>
Tee 3 traitia nimillä Trait1,
Trait2 ja Trait3. Olkoon ensimmäisessä
traitissa menetelmä method, joka palauttaa
1, toisessa traitissa - samaniminen
menetelmä, joka palauttaa 2, ja kolmannessa
traitissa - samaniminen menetelmä,
joka palauttaa 3.
Tee luokka Test, joka käyttää
kaikkia kolmea tekemäämme traitia. Tee tähän
luokkaan menetelmä getSum, joka palauttaa
liitettyjen traittien menetelmien tulosten summan.