การแก้ไขความขัดแย้งของเมธอดใน Traits ของ OOP ใน PHP

เนื่องจากคลาสหนึ่งสามารถใช้งานหลาย Traits ได้ ดังนั้นปัญหาที่อาจเกิดขึ้นคือเมื่อมีสอง Traits ที่มีเมธอดชื่อเดียวกัน

ในกรณีนี้ PHP จะแสดงข้อผิดพลาดร้ายแรง (fatal error) เพื่อแก้ไขสถานการณ์ จะต้องแก้ไขความขัดแย้งของชื่ออย่างชัดเจน วิธีทำอย่างไร มาดูกันในทางปฏิบัติ

สมมติว่าเรามีสอง Traits ที่มีเมธอด method เหมือนกัน:

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

สมมติว่ายังมีคลาส Test ที่ใช้งานทั้งสอง Traits ของเรา หากเพียงแค่เชื่อมต่อทั้งสอง Traits ไปยังคลาสของเรา PHP จะแสดงข้อผิดพลาด เนื่องจาก Traits มีเมธอดที่ตรงกัน:

php<?php
  // รหัสนี้จะแสดงข้อผิดพลาด!
  class Test
  {
    use Trait1, Trait2; // เชื่อมต่อ Traits
  }
?>

เรามาแก้ไขความขัดแย้งของชื่อของ Traits ของเรากัน สำหรับสิ่งนี้มีโอเปอเรเตอร์พิเศษ insteadof โดยใช้โอเปอเรเตอร์นี้ เราจะใช้เมธอด method ของ Trait Trait1 แทนเมธอดเดียวกันของ Trait Trait2:

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

อย่างที่คุณเห็น ไวยากรณ์มีดังนี้: เริ่มจากชื่อ Trait ตามด้วยโคลอนสองอัน ตามด้วยชื่อเมธอด ตามด้วยโอเปอเรเตอร์ insteadof ของเรา และชื่อของ Trait ที่สอง

ลองทดสอบกัน:

php<?php
  class Test
  {
    use Trait1, Trait2 {
      Trait1::method insteadof Trait2;
    }
    
    public function __construct()
    {
      echo $this->method(); // จะแสดง 1 เพราะนี่คือเมธอดของ Trait แรก
    }
  }
  
  new Test;
?>

ดังนั้นในคลาสของเราเราได้ระบุว่าหากใช้เมธอด method ควรนำมาจาก Trait แรก สามารถทำตรงกันข้ามได้ - นำเมธอดของ Trait ที่สอง:

php<?php
  class Test
  {
    use Trait1, Trait2 {
      Trait2::method insteadof Trait1;
    }
    
    public function __construct()
    {
      echo $this->method(); // จะแสดง 2 เพราะนี่คือเมธอดของ Trait ที่สอง
    }
  }
  
  new Test;
?>

ไม่ว่ากรณีใดก็ตาม หากเราระบุให้ใช้เมธอดของหนึ่ง Trait เมธอดของ Trait ที่สองจะไม่สามารถเข้าถึงได้ สามารถใช้เมธอดของ Trait ที่สองได้โดยเปลี่ยนชื่อผ่านคำสำคัญ 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;
?>

หากต้องการ สามารถเปลี่ยนชื่อเมธอดของ Trait แรกได้:

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

สร้าง Traits จำนวน 3 ชื่อว่า Trait1, Trait2 และ Trait3 ให้ใน Trait แรกมีเมธอด method ที่คืนค่า 1 ใน Trait ที่สอง - เมธอดชื่อเดียวกันที่คืนค่า 2 และใน Trait ที่สาม - เมธอดชื่อเดียวกันที่คืนค่า 3

Задание 2

สร้างคลาส Test ที่ใช้ทั้งสาม Traits ที่เราสร้างขึ้น สร้างเมธอด getSum ในคลาสนี้ที่คืนค่าผลรวมของผลลัพธ์จากเมธอดของ Traits ที่เชื่อมต่อ