A trait metódusok konfliktusainak feloldása az OOP-ban PHP-ben

Mivel egy osztály több traitet is használhat, előfordulhat egy olyan probléma, amikor két traitnek azonos nevű metódusa van.

Ebben az esetben a PHP halálos hibát jelez. A helyzet javításához explicit módon kell feloldani a névkonfliktust. Hogyan történik ez - nézzük meg a gyakorlatban.

Tegyük fel, hogy van két traitünk azonos method metódussal:

php<?php
  trait Trait1
  {
    private function method()
    {
      return 1;
    }
  }
  
  trait Trait2
  {
    private function method()
    {
      return 2;
    }
  }
?>

Tegyük fel, hogy van egy Test osztályunk is, amely mindkét traitünket használja. Ha egyszerűen mindkét traitet csatoljuk az osztályunkhoz, akkor a PHP hibát jelez, mivel a trait-eknek vannak egymást fedő metódusaik:

php<?php
  // Ez a kód hibát fog jelezni!
  class Test
  {
    use Trait1, Trait2; // trait-ek csatolása
  }
?>

Oldjuk fel a trait-jeink névkonfliktusát. Ehhez létezik egy speciális operátor, a insteadof. Ezzel az operátorral a Trait1 trait method metódusát fogjuk használni a Trait2 trait azonos nevű metódusa helyett:

php<?php
  class Test
  {
    use Trait1, Trait2 {
      Trait1::method insteadof Trait2;
    }
  }
  
  new Test;
?>

Amint látod, a szintaxis a következő: először a trait neve, majd kettőspont, majd a metódus neve, majd a insteadof operátorunk és a második trait neve.

Vizsgáljuk meg:

php<?php
  class Test
  {
    use Trait1, Trait2 {
      Trait1::method insteadof Trait2;
    }
    
    public function __construct()
    {
      echo $this->method(); // 1-et ír ki, mert ez az első trait metódusa
    }
  }
  
  new Test;
?>

Tehát az osztályunkban meghatároztuk, hogy ha a method metódust használjuk, akkor azt az első traitből kell venni. Megfordítható is - vehetjük a második trait metódusát:

php<?php
  class Test
  {
    use Trait1, Trait2 {
      Trait2::method insteadof Trait1;
    }
    
    public function __construct()
    {
      echo $this->method(); // 2-t ír ki, mert ez a második trait metódusa
    }
  }
  
  new Test;
?>

Mindenesetre, ha azt határozzuk meg, hogy egy trait metódusát használjuk, akkor a másik trait metódusa elérhetetlenné válik. Használhatjuk a másik trait metódusát is, átnevezve azt a as kulcsszóval, így:

php<?php
  class Test
  {
    use Trait1, Trait2 {
      Trait1::method insteadof Trait2;
      Trait2::method as method2;
    }
    
    public function __construct()
    {
      echo $this->method() + $this->method2(); // 3-at fog kiírni
    }
  }
  
  new Test;
?>

Szükség esetén átnevezhetjük az első trait metódusát is:

php<?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-at fog kiírni
    }
  }
  
  new Test;
?>

A as kulcsszó használata a fő metódus insteadof-val való megadása nélkül nem megengedett, ez hibát jelezne:

php<?php
  // Ez az osztály hibát fog jelezni:
  class Test
  {
    use Trait1, Trait2 {
      Trait1::method as method1;
      Trait2::method as method2;
    }
    
    public function __construct()
    {
      echo $this->method1() + $this->method2();
    }
  }
  
  new Test;
?>
Задание 1

Készíts 3 traitet Trait1, Trait2 és Trait3 nevekkel. Legyen az első traitben egy method metódus, amely 1-et ad vissza, a második traitben - egy azonos nevű metódus, amely 2-t ad vissza, a harmadik traitben pedig - egy azonos nevű metódus, amely 3-at ad vissza.

Задание 2

Készíts egy Test osztályt, amely mindhárom általunk létrehozott traitet használja. Készíts ebben az osztályban egy getSum metódust, amely visszaadja a csatolt trait-ek metódusainak eredményeinek összegét.