การแก้ไขความขัดแย้งของเมธอดใน Traits ของ OOP ใน PHP
เนื่องจากคลาสหนึ่งสามารถใช้งานหลาย Traits ได้ ดังนั้นปัญหาที่อาจเกิดขึ้นคือเมื่อมีสอง Traits ที่มีเมธอดชื่อเดียวกัน
ในกรณีนี้ PHP จะแสดงข้อผิดพลาดร้ายแรง (fatal error) เพื่อแก้ไขสถานการณ์ จะต้องแก้ไขความขัดแย้งของชื่ออย่างชัดเจน วิธีทำอย่างไร มาดูกันในทางปฏิบัติ
สมมติว่าเรามีสอง Traits ที่มีเมธอด method เหมือนกัน:
<?php
trait Trait1
{
private function method()
{
return 1;
}
}
trait Trait2
{
private function method()
{
return 2;
}
}
?>
สมมติว่ายังมีคลาส Test ที่ใช้งานทั้งสอง Traits ของเรา หากเพียงแค่เชื่อมต่อทั้งสอง Traits ไปยังคลาสของเรา PHP จะแสดงข้อผิดพลาด เนื่องจาก Traits มีเมธอดที่ตรงกัน:
<?php
// รหัสนี้จะแสดงข้อผิดพลาด!
class Test
{
use Trait1, Trait2; // เชื่อมต่อ Traits
}
?>
เรามาแก้ไขความขัดแย้งของชื่อของ Traits ของเรากัน สำหรับสิ่งนี้มีโอเปอเรเตอร์พิเศษ insteadof โดยใช้โอเปอเรเตอร์นี้ เราจะใช้เมธอด method ของ Trait Trait1 แทนเมธอดเดียวกันของ Trait Trait2:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
}
new Test;
?>
อย่างที่คุณเห็น ไวยากรณ์มีดังนี้: เริ่มจากชื่อ Trait ตามด้วยโคลอนสองอัน ตามด้วยชื่อเมธอด ตามด้วยโอเปอเรเตอร์ insteadof ของเรา และชื่อของ Trait ที่สอง
ลองทดสอบกัน:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
public function __construct()
{
echo $this->method(); // จะแสดง 1 เพราะนี่คือเมธอดของ Trait แรก
}
}
new Test;
?>
ดังนั้นในคลาสของเราเราได้ระบุว่าหากใช้เมธอด method ควรนำมาจาก Trait แรก สามารถทำตรงกันข้ามได้ - นำเมธอดของ Trait ที่สอง:
<?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
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
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
// คลาสนี้จะแสดงข้อผิดพลาด:
class Test
{
use Trait1, Trait2 {
Trait1::method as method1;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method1() + $this->method2();
}
}
new Test;
?>
สร้าง Traits จำนวน 3 ชื่อว่า Trait1, Trait2 และ Trait3 ให้ใน Trait แรกมีเมธอด method ที่คืนค่า 1 ใน Trait ที่สอง - เมธอดชื่อเดียวกันที่คืนค่า 2 และใน Trait ที่สาม - เมธอดชื่อเดียวกันที่คืนค่า 3
สร้างคลาส Test ที่ใช้ทั้งสาม Traits ที่เราสร้างขึ้น สร้างเมธอด getSum ในคลาสนี้ที่คืนค่าผลรวมของผลลัพธ์จากเมธอดของ Traits ที่เชื่อมต่อ