ՕՕՊ-ում PHP-ի տրեյթների մեթոդների կոնֆլիկտների լուծում

Քանի որ մեկ դաս կարող է օգտագործել մի քանի տրեյթ, մեզ կարող է սպասել խնդիր, որը առաջանում է, երբ երկու տրեյթ ունեն նույնանուն մեթոդներ:

Այս դեպքում PHP-ն կտա ֆատալ սխալ: Իրավիճակը ուղղելու համար անհրաժեշտ կլինի լուծել անվանումների կոնֆլիկտը հստակ կերպով: Ինչպես է դա արվում - կտեսնենք գործնականում:

Ենթադրենք, մենք ունենք երկու տրեյթ նույն մեթոդով method:

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

Ենթադրենք, մենք նաև ունենք Test դաս, որը օգտագործում է մեր երկու տրեյթները: Եթե պարզապես միացնենք երկու տրեյթները մեր դասին, ապա PHP-ն կտա սխալ, քանի որ տրեյթներն ունեն համընկնող մեթոդներ:

php<?php
  // Այս կոդը կտա սխալ:
  class Test
  {
    use Trait1, Trait2; // միացնում ենք տրեյթները
  }
?>

Եկեք լուծենք մեր տրեյթների անվանումների կոնֆլիկտը: Դրա համար գոյություն ունի հատուկ օպերատոր insteadof: Այս օպերատորի օգնությամբ կօգտագործենք Trait1 տրեյթի method մեթոդը Trait2 տրեյթի նույն մեթոդի փոխարեն:

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

Ինչպես տեսնում եք, այստեղ շարահյուսությունը հետևյալն է. սկզբում տրեյթի անունը, ապա երկու միջակետ, ապա մեթոդի անունը, ապա մեր insteadof օպերատորը և երկրորդ տրեյթի անունը:

Եկեք ստուգենք.

php<?php
  class Test
  {
    use Trait1, Trait2 {
      Trait1::method insteadof Trait2;
    }
    
    public function __construct()
    {
      echo $this->method(); // կարտադրի 1, քանի որ սա առաջին տրեյթի մեթոդն է
    }
  }
  
  new Test;
?>

Այսպիսով, մեր դասում մենք ասացինք, որ եթե օգտագործվում է method մեթոդը, ապա պետք է վերցնել այն առաջին տրեյթից: Կարելի է նաև հակառակը - վերցնել երկրորդ տրեյթի մեթոդը.

php<?php
  class Test
  {
    use Trait1, Trait2 {
      Trait2::method insteadof Trait1;
    }
    
    public function __construct()
    {
      echo $this->method(); // կարտադրի 2, քանի որ սա երկրորդ տրեյթի մեթոդն է
    }
  }
  
  new Test;
?>

Ինչպես և լինի, եթե մենք նշում ենք օգտագործել մեկ տրեյթի մեթոդը, ապա երկրորդ տրեյթի մեթոդը դառնում է անհասանելի: Կարելի է օգտագործել նաև երկրորդ տրեյթի մեթոդը՝ այն վերանվանելով as հիմնաբառի միջոցով, ահա այսպես.

php<?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<?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<?php
  // Այս դասը կտա սխալ.
  class Test
  {
    use Trait1, Trait2 {
      Trait1::method as method1;
      Trait2::method as method2;
    }
    
    public function __construct()
    {
      echo $this->method1() + $this->method2();
    }
  }
  
  new Test;
?>
Задание 1

Ստեղծեք 3 տրեյթ Trait1, Trait2 և Trait3 անուններով: Թող առաջին տրեյթում լինի method մեթոդ, որը վերադարձնում է 1, երկրորդ տրեյթում - նույնանուն մեթոդ, որը վերադարձնում է 2, իսկ երրորդ տրեյթում - նույնանուն մեթոդ, որը վերադարձնում է 3:

Задание 2

Ստեղծեք Test դաս, որն օգտագործում է մեր ստեղծած բոլոր երեք տրեյթները: Այս դասում ստեղծեք getSum մեթոդ, որը վերադարձնում է միացված տրեյթների մեթոդների արդյունքների գումարը: