ტრეიტების მეთოდების კონფლიქტების გადაჭრა OOP-ში 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, რომელიც აბრუნებს შეკავშირებული ტრეიტების მეთოდების შედეგების ჯამს.