Giải quyết xung đột phương thức trait trong OOP PHP
Vì một lớp có thể sử dụng nhiều trait, nên chúng ta có thể gặp phải vấn đề xảy ra khi hai trait có các phương thức trùng tên.
Trong trường hợp này, PHP sẽ đưa ra lỗi nghiêm trọng. Để khắc phục tình huống, cần phải giải quyết xung đột tên một cách rõ ràng. Cách thực hiện - chúng ta sẽ xem xét trong thực tế.
Giả sử chúng ta có hai trait với cùng một
phương thức method:
<?php
trait Trait1
{
private function method()
{
return 1;
}
}
trait Trait2
{
private function method()
{
return 2;
}
}
?>
Giả sử chúng ta cũng có lớp Test,
sử dụng cả hai trait của chúng ta. Nếu chỉ đơn giản
kết nối cả hai trait vào lớp của chúng ta, thì
PHP sẽ báo lỗi, vì các trait có
phương thức trùng nhau:
<?php
// Mã này sẽ báo lỗi!
class Test
{
use Trait1, Trait2; // kết nối các trait
}
?>
Hãy giải quyết xung đột tên
của các trait chúng ta. Đối với điều này tồn tại toán tử đặc biệt
insteadof. Với sự trợ giúp của toán tử này
sẽ sử dụng phương thức method của trait
Trait1 thay vì phương thức tương tự của trait
Trait2:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
}
new Test;
?>
Như bạn thấy, cú pháp ở đây như sau: đầu tiên là
tên trait, sau đó hai dấu hai chấm, sau đó là tên
phương thức, sau đó toán tử của chúng ta insteadof
và tên của trait thứ hai.
Hãy kiểm tra:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
public function __construct()
{
echo $this->method(); // sẽ hiển thị 1, vì đây là phương thức của trait đầu tiên
}
}
new Test;
?>
Vì vậy, trong lớp của chúng ta, chúng ta đã nói rằng nếu
sử dụng phương thức method, thì nên
lấy nó từ trait đầu tiên. Cũng có thể ngược lại
- lấy phương thức của trait thứ hai:
<?php
class Test
{
use Trait1, Trait2 {
Trait2::method insteadof Trait1;
}
public function __construct()
{
echo $this->method(); // sẽ hiển thị 2, vì đây là phương thức của trait thứ hai
}
}
new Test;
?>
Trong mọi trường hợp, nếu chúng ta chỉ định sử dụng
phương thức của một trait, thì phương thức của trait thứ hai
sẽ trở nên không khả dụng. Có thể sử dụng
cả phương thức của trait thứ hai, bằng cách đổi tên nó
thông qua từ khóa as, như thế này:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method() + $this->method2(); // sẽ hiển thị 3
}
}
new Test;
?>
Nếu muốn, có thể đổi tên cả phương thức của trait đầu tiên :
<?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(); // sẽ hiển thị 3
}
}
new Test;
?>
Sử dụng từ khóa as mà không có
xác định phương thức chính thông qua insteadof
là không thể, điều này sẽ gây ra lỗi:
<?php
// Lớp này sẽ báo lỗi:
class Test
{
use Trait1, Trait2 {
Trait1::method as method1;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method1() + $this->method2();
}
}
new Test;
?>
Tạo 3 trait với tên Trait1,
Trait2 và Trait3. Giả sử trong trait đầu tiên
có phương thức method, trả về
1, trong trait thứ hai - phương thức cùng tên
, trả về 2, và trong trait thứ ba
- phương thức cùng tên,
trả về 3.
Tạo lớp Test, sử dụng
tất cả ba trait do chúng ta tạo ra. Tạo trong
lớp này phương thức getSum, trả về
tổng kết quả của các phương thức từ các trait được kết nối.