Giải quyết xung đột giữa các đặc tính
Thuộc phần Lập trình hướng đối tượng trong hành trình PHP của Coddy. Bài học 53 trên 91.
Khi hai trait định nghĩa các phương thức trùng tên, PHP sẽ báo lỗi nghiêm trọng. Bạn phải chỉ rõ cho PHP cách xử lý xung đột này bằng các toán tử insteadof và as.
<?php
trait FileLogger {
public function log(string $message): void {
echo "File: $message";
}
}
trait DatabaseLogger {
public function log(string $message): void {
echo "DB: $message";
}
}
class Application {
use FileLogger, DatabaseLogger {
FileLogger::log insteadof DatabaseLogger;
DatabaseLogger::log as logToDatabase;
}
}
$app = new Application();
$app->log("Error occurred");
$app->logToDatabase("Error occurred");
Đầu ra:
File: Error occurred
DB: Error occurredToán tử insteadof chọn phương thức của trait nào sẽ được dùng khi có xung đột. Trong ví dụ này, FileLogger::log được chọn và trở thành phương thức log() mặc định. Toán tử as tạo bí danh, cho phép bạn truy cập phương thức của trait còn lại bằng một tên khác.
Bạn cũng có thể dùng as để thay đổi phạm vi hiển thị của một phương thức:
<?php
trait Greeting {
public function sayHello(): void {
echo "Hello!";
}
}
class Person {
use Greeting {
sayHello as private;
}
}
Điều này khiến sayHello() chỉ có thể được truy cập riêng trong lớp Person, dù phương thức này là công khai trong trait. Cách giải quyết xung đột giúp bạn kiểm soát chi tiết cách các phương thức của trait tích hợp vào lớp.
Thử thách
DễHãy xây dựng một hệ thống thông báo, trong đó các kênh khác nhau có thể gửi tin nhắn, nhưng chúng ta cần giải quyết xung đột khi nhiều trait cung cấp phương thức cùng tên.
Bạn sẽ sắp xếp code trong bốn tệp:
EmailNotifier.php: Tạo một trait có tênEmailNotifiervới phương thứcnotify(string $message)trả về"Email: [message]".SmsNotifier.php: Tạo một trait có tênSmsNotifiervới phương thứcnotify(string $message)trả về"SMS: [message]".AlertService.php: Tạo lớpAlertServicesử dụng cả hai trait. Vì cả hai trait đều có phương thứcnotify(), bạn cần giải quyết xung đột này:- Dùng
EmailNotifier::notifylàm phương thứcnotify()mặc định - Tạo bí danh
notifyBySmscho phương thứcSmsNotifier::notify
notifyAll(string $message)gọi cả hai phương thức thông báo và trả về kết quả của chúng trên các dòng riêng biệt.- Dùng
main.php: Nạp tất cả các tệp cần thiết và tạo một đối tượngAlertService. Bạn sẽ nhận một đầu vào: một chuỗi tin nhắn. In ra ba dòng:- Kết quả gọi
notify()với tin nhắn đó - Kết quả gọi
notifyBySms()với tin nhắn đó - Kết quả gọi
notifyAll()với tin nhắn đó
- Kết quả gọi
Ví dụ này minh họa cách insteadof xác định phương thức của trait nào sẽ được dùng khi xảy ra xung đột tên, còn as cho phép bạn tiếp tục dùng phương thức của trait còn lại dưới một tên khác.
Tự làm thử
<?php
require_once 'AlertService.php';
// Đọc đầu vào
$message = trim(fgets(STDIN));
// TODO: Tạo một instance của AlertService
// TODO: In ra kết quả khi gọi notify() với thông điệp
// TODO: In ra kết quả khi gọi notifyBySms() với thông điệp
// TODO: In ra kết quả khi gọi notifyAll() với thông điệp
?>Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng về OOP
Tệp bên ngoàiGiới thiệu về OOPLớp và đối tượngTừ khóa $thisPhương thứcThuộc tínhHàm khởi tạo (__construct)Hàm hủy (__destruct)Ôn tập: máy tính đơn giản4Kế thừa
Kế thừa cơ bảnTừ khóa parent::Ghi đè phương thứcTừ khóa finalLớp trừu tượngÔn tập: hệ thống phân cấp nhân viên7Đóng gói
Công khai, được bảo vệ, riêng tưTìm hiểu sâu về bộ điều chỉnh quyền truy cậpGetter và setterẨn thông tinRút gọn hàm khởi tạo (8.0)Ôn tập: hệ thống hồ sơ học sinh2Không gian tên và tự động nạp
Giới thiệu về không gian tênTừ khóa useChuẩn tự động nạp PSR-4Trình tự động nạp của ComposerÔn tập: dự án có tổ chức5Giao diện và hợp đồng
Giới thiệu về giao diệnTriển khai giao diệnTriển khai nhiều giao diệnGiao diện và lớp trừu tượngGợi ý kiểu với giao diệnÔn tập: Máy tính hình học8Phương thức ma thuật
Giới thiệu về phương thức ma thuật__toString và __debugInfo__get, __set, __isset, __unset__call và __callStatic__clone và sao chép đối tượng__serialize và __unserializeÔn tập: Bộ sưu tập tùy chỉnh3Thuộc tính của lớp
Thuộc tính instance và staticHằng số trong lớpPhương thức và thuộc tính staticThuộc tính private và protectedThuộc tính chỉ đọc (PHP 8.1)Ôn tập: Trình quản lý tài khoản ngân hàng6Đa hình
Xem lại việc ghi đè phương thứcĐa hình qua giao diệnGợi ý kiểu và kiểu hợpLiên kết tĩnh muộnÔn tập: bộ xử lý thanh toán9Đặc tính
Giới thiệu về đặc tínhSử dụng nhiều đặc tínhGiải quyết xung đột giữa các đặc tínhPhương thức trừu tượng trong đặc tínhĐặc tính và kế thừaTự luyện tập: Trình biên dịch PHP online